diff --git a/LICENSE b/LICENSE index 79882c7e59aa20d9ea2125af972e0cb4672df5db..4e2971e9ea7d99331dfe46c7d52e17ae1fa2c436 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ DSpace source code license: -Copyright (c) 2002-2012, DuraSpace. All rights reserved. +Copyright (c) 2002-2013, DuraSpace. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY index ce4b326810e207875e34108be63c0b606f752156..011574ae3f9a485de7a53c675630ea4cef339dff 100644 --- a/LICENSES_THIRD_PARTY +++ b/LICENSES_THIRD_PARTY @@ -52,22 +52,30 @@ Apache Software License, Version 2.0 (http://opensource.org/licenses/apache2.0) * 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/ + * Evo Inflector (org.atteo:*) - http://www.atteo.org/evo-framework/inflector/ * 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/ + * Jackson (org.codehaus.jackson:*) - http://jackson.codehaus.org/ + * Jettison (org.codejaus.jettison:*) - http://jettison.codehaus.org/ * Jetty (org.mortbay.jetty:*) - http://jetty.codehaus.org/jetty/license.html * Lyncode XOAI (com.lyncode:xoai) - http://www.lyncode.com/ + * noggit (org.noggit:noggit) - http://noggit.org/ + * oai4j (se.kb:oai4j) - http://oai4j-client.sourceforge.net/ * OpenCSV (net.sf.opencsv:*) - http://opencsv.sourceforge.net/ * Rome (net.java.dev.rome:*, org.rometools:*, rome:*) - http://rometools.org/ + * spatial4j (com.spatial4j:*) - http://spatial4j.com/ * 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) + * asm (asm:*) - http://asm.ow2.org/ * 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/ + * jargon (org.dspace:jargon) - http://www.sdsc.edu/srb/index.php/Jargon * 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/ @@ -81,15 +89,19 @@ Common Development and Distribution License (CDDL) v1.0 (http://www.opensource.o * 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 Development and Distribution License (CDDL) v1.1 (http://glassfish.java.net/public/CDDL+GPL_1_1.html) + * JAXB (com.sun.xml.bind:*) - http://jaxb.java.net/ + * Jersey (com.sun.jersey.*) - https://jersey.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 + * METS Java Toolkit (org.dspace.mets:*) - http://hul.harvard.edu/mets/ * Text-mining (org.dspace.dependencies:dspace-tm-extractors) - http://code.google.com/p/text-mining/ * XOM (xom:*) - http://www.xom.nu/ @@ -100,11 +112,18 @@ MIT / X11 License (or adaptations) (http://www.opensource.org/licenses/MIT) Mozilla Public License (http://www.opensource.org/licenses/MPL-2.0) * H2 database (com.h2database:*) - http://www.h2database.com/html/license.html + +New BSD License (http://opensource.org/licenses/bsd-license.php) + * Biblio-Transformation Engine (gr.ekt.bte:*) - http://github.com/EKT/Biblio-Transformation-Engine Other Open Source Licenses: * AOP Alliance (aopalliance:*) - Public Domain: http://aopalliance.sourceforge.net/ + * backport-util-concurrent (backport-util-concurrent:*) - Public Domain: http://creativecommons.org/licenses/publicdomain + * coverity-escapers (com.coverity.security:*) - Modified BSD + * Handle API (org.dspace:handle) - Handle Public License Agreement: http://www.handle.net/HSj/hdlnet-2-LICENSE.pdf * 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 + * OCLC Harvester2 (org.dspace:oclc-harvester2) - OCLC Research Public License: http://www.oclc.org/research/activities/software/license/v2final.html * 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 diff --git a/README b/README index 0490692d6c92103b022e3468ca829aa28cba84e5..0788ec5eb9ac3217fc60909f86e96af57cf7a2f4 100644 --- a/README +++ b/README @@ -1,6 +1,9 @@ -Installation instructions are included in this release package under +Installation instructions may be found in DSpace-Manual.pdf, offered +with the source archives in the SourceForge project: - - dspace/docs/DSpace-Manual.pdf + http://sourceforge.net/projects/dspace/files/DSpace%20Stable/VERSION/ + +(Replace "VERSION" with the version you are installing, such as "4.0".) DSpace version information can be viewed online at - https://wiki.duraspace.org/display/DSDOC/ @@ -51,4 +54,4 @@ places to seek help, news articles and lists of other users, please see: DSpace source code licensing information available online at: - http://www.dspace.org/license/ -Copyright (c) 2002-2012, DuraSpace. All rights reserved. +Copyright (c) 2002-2013, DuraSpace. All rights reserved. diff --git a/build.properties b/build.properties index 382044af1d89b14da34a50683bd84356a6749270..2e3d3ce0c1819f9a6dc923d90fdb450dde15ef38 100644 --- a/build.properties +++ b/build.properties @@ -22,22 +22,22 @@ # 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.install.dir=/dspace # DSpace host name - should match base URL. Do not include port number -dspace.hostname = dspacesnj.c3sl.ufpr.br +dspace.hostname = localhost # DSpace base host URL. Include port number etc. -dspace.baseUrl = dspacesnj.c3sl.ufpr.br +dspace.baseUrl = http://localhost:8080 # Name of the site -dspace.name = DSpace Estacao Juventude +dspace.name = DSpace at My University # Solr server -solr.server=http://localhost/solr +solr.server=http://localhost:8080/solr # Default language for metadata values -default.language = pt_BR +default.language = en_US ########################## # DATABASE CONFIGURATION # @@ -85,7 +85,7 @@ db.poolname = dspacepool ####################### # SMTP mail server -mail.server = smtp.c3sl.ufpr.br +mail.server = smtp.example.com # SMTP mail server authentication username and password (if required) # mail.server.username = myusername @@ -97,21 +97,21 @@ mail.server.password= mail.server.port = 25 # From address for mail -mail.from.address = dsparticipatorio@c3sl.ufpr.br +mail.from.address = dspace-noreply@myu.edu # Currently limited to one recipient! -mail.feedback.recipient = dsparticipatorio@c3sl.ufpr.br +mail.feedback.recipient = dspace-help@myu.edu # General site administration (Webmaster) e-mail -mail.admin = dsparticipatorio@c3sl.ufpr.br +mail.admin = dspace-help@myu.edu # Recipient for server errors and alerts #mail.alert.recipient = email-address-here -mail.alert.recipient=dsparticipatorio@c3sl.ufpr.br +mail.alert.recipient= # Recipient for new user registration emails #mail.registration.notify = email-address-here -mail.registration.notify=dsparticipatorio@c3sl.ufpr.br +mail.registration.notify= ######################## @@ -149,3 +149,13 @@ http.proxy.host = # port number of proxy server http.proxy.port = + +##################### +# LOGLEVEL SETTINGS # +##################### +loglevel.other = INFO +# 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 +loglevel.dspace = INFO +# loglevel.dspace: Log level for all DSpace-specific code (org.dspace.*) +# Possible values (from most to least info): DEBUG, INFO, WARN, ERROR, FATAL 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/bulkedit/package-info.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..5393ca8aa179985956ef16a5faeb4b9350011636 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/package-info.java @@ -0,0 +1,22 @@ +/** + * 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/ + */ + +/** + * <p>The DSpace Batch Metadata Editor, which uses a CSV file to export/import + * item metadata.</p> + * <p> + * <ul> + * <li>works on items, communities, collections or the whole site</li> + * <li>can also create new items, delete items and withdraw/restore them</li> + * <li>cannot export/import bitstreams</li> + * </ul> + */ + +package org.dspace.app.bulkedit; + + 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/BTEBatchImportService.java b/dspace-api/src/main/java/org/dspace/app/itemimport/BTEBatchImportService.java new file mode 100644 index 0000000000000000000000000000000000000000..1513eaecf4e29167430d6680700841f8adacf8a1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/BTEBatchImportService.java @@ -0,0 +1,93 @@ +/** + * 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 gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.TransformationEngine; +import gr.ekt.bte.dataloader.FileDataLoader; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + + + +/** + * This class acts as a Service in the procedure ot batch import using the Biblio-Transformation-Engine + */ +public class BTEBatchImportService +{ + + TransformationEngine transformationEngine; + Map<String, DataLoader> dataLoaders = new HashMap<String, DataLoader>(); + Map<String, String> outputMap = new HashMap<String,String>(); + + /** + * Default constructor + */ + public BTEBatchImportService() + { + 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; + } + + /** + * + * @return the outputMapping + */ + public Map<String, String> getOutputMap() { + return outputMap; + } + + /** + * Setter method for the outputMapping + * @param outputMapping + */ + public void setOutputMap(Map<String, String> outputMap) { + this.outputMap = outputMap; + } + + public TransformationEngine getTransformationEngine() { + return transformationEngine; + } + + public void setTransformationEngine(TransformationEngine transformationEngine) { + this.transformationEngine = transformationEngine; + } + + public List<String> getFileDataLoaders(){ + List<String> result = new ArrayList<String>(); + + for (String key : dataLoaders.keySet()){ + DataLoader dl = dataLoaders.get(key); + if (dl instanceof FileDataLoader){ + result.add(key); + } + } + return result; + } +} \ No newline at end of file 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/CommandRunner.java b/dspace-api/src/main/java/org/dspace/app/launcher/CommandRunner.java new file mode 100644 index 0000000000000000000000000000000000000000..259acf0fa05ebe6b7c8fe73b7b2ec0d2dd127592 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/launcher/CommandRunner.java @@ -0,0 +1,107 @@ +/** + * 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.launcher; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StreamTokenizer; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author mwood + */ +public class CommandRunner +{ + public static void main(String[] args) + throws FileNotFoundException, IOException + { + if (args.length > 0) + { + runManyCommands(args[0]); + } + else + { + runManyCommands("-"); + } + // There is no sensible way to use the status returned by runManyCommands(). + // If called from the command line then we would want to return it + // through System.exit(). But if called (normally) from ScriptLauncher, + // there is no way to return it and we don't want to interrupt + // ScriptLauncher. + // + // "'tis a puzzlement." -- the King of Siam + } + + /** + * Read a file of command lines and execute each in turn. + * + * @param doc details of recognized commands. + * @param script the file of command lines to be executed. + * @return + * @throws FileNotFoundException + * @throws IOException + */ + static int runManyCommands(String script) + throws FileNotFoundException, IOException + { + Reader input; + if ("-".equals(script)) + { + input = new InputStreamReader(System.in); + } + else + { + input = new FileReader(script); + } + + StreamTokenizer tokenizer = new StreamTokenizer(input); + + tokenizer.eolIsSignificant(true); + + tokenizer.ordinaryChar('-'); + tokenizer.wordChars('-', '-'); + + tokenizer.ordinaryChars('0', '9'); + tokenizer.wordChars('0', '9'); + + tokenizer.ordinaryChar('.'); + tokenizer.wordChars('.', '.'); + + tokenizer.ordinaryChar('@'); + tokenizer.wordChars('@', '@'); + + int status = 0; + List<String> tokens = new ArrayList<String>(); + while (StreamTokenizer.TT_EOF != tokenizer.nextToken()) + { + if (StreamTokenizer.TT_EOL == tokenizer.ttype) + { + if (tokens.size() > 0) + { + status = ScriptLauncher.runOneCommand(tokens.toArray(new String[tokens.size()])); + if (status > 0) + { + break; + } + tokens.clear(); + } + } + else + { + tokens.add(tokenizer.sval); + } + } + + return status; + } +} 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/requestitem/RequestItemAuthor.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemAuthor.java new file mode 100644 index 0000000000000000000000000000000000000000..db1a735a9b716abbf3810456824dc74f718ac0d3 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemAuthor.java @@ -0,0 +1,34 @@ +/** + * 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.requestitem; + +/** + * Simple DTO to transfer data about the corresponding author for the Request + * Copy feature + * + * @author Andrea Bollini + * + */ +public class RequestItemAuthor { + private String fullName; + private String email; + + public RequestItemAuthor(String fullName, String email) { + super(); + this.fullName = fullName; + this.email = email; + } + + public String getEmail() { + return email; + } + + public String getFullName() { + return fullName; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemAuthorExtractor.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemAuthorExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..d94c7320deeac661aaf3f9eea4948231b99ae8ab --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemAuthorExtractor.java @@ -0,0 +1,25 @@ +/** + * 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.requestitem; + +import java.sql.SQLException; + +import org.dspace.content.Item; +import org.dspace.core.Context; + +/** + * Interface to abstract the strategy for select the author to contact for + * request copy + * + * @author Andrea Bollini + * + */ +public interface RequestItemAuthorExtractor { + public RequestItemAuthor getRequestItemAuthor(Context context, Item item) + throws SQLException; +} diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemMetadataStrategy.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemMetadataStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..b5ed3a3e67b3a25f598699a934a6cb2e07128b55 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemMetadataStrategy.java @@ -0,0 +1,75 @@ +/** + * 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.requestitem; + +import java.sql.SQLException; + +import org.apache.commons.lang.StringUtils; +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.core.I18nUtil; + +/** + * Try to look to an item metadata for the corresponding author name and email. + * Failover to the RequestItemSubmitterStrategy + * + * @author Andrea Bollini + * + */ +public class RequestItemMetadataStrategy extends RequestItemSubmitterStrategy { + + private String emailMetadata; + private String fullNameMatadata; + + public RequestItemMetadataStrategy() { + } + + @Override + public RequestItemAuthor getRequestItemAuthor(Context context, Item item) + throws SQLException { + if (emailMetadata != null) + { + DCValue[] vals = item.getMetadata(emailMetadata); + if (vals.length > 0) + { + String email = vals[0].value; + String fullname = null; + if (fullNameMatadata != null) + { + DCValue[] nameVals = item.getMetadata(fullNameMatadata); + if (nameVals.length > 0) + { + fullname = nameVals[0].value; + } + } + + if (StringUtils.isBlank(fullname)) + { + fullname = I18nUtil + .getMessage( + "org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed", + context); + } + RequestItemAuthor author = new RequestItemAuthor( + fullname, email); + return author; + } + } + return super.getRequestItemAuthor(context, item); + } + + public void setEmailMetadata(String emailMetadata) { + this.emailMetadata = emailMetadata; + } + + public void setFullNameMatadata(String fullNameMatadata) { + this.fullNameMatadata = fullNameMatadata; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java new file mode 100644 index 0000000000000000000000000000000000000000..b7fde10f1d5a93b9eea5ef6e200bb262a7a43951 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/requestitem/RequestItemSubmitterStrategy.java @@ -0,0 +1,36 @@ +/** + * 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.requestitem; + +import java.sql.SQLException; + +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.eperson.EPerson; + +/** + * Basic strategy that looks to the original submitter. + * + * @author Andrea Bollini + * + */ +public class RequestItemSubmitterStrategy implements RequestItemAuthorExtractor { + + public RequestItemSubmitterStrategy() { + } + + @Override + public RequestItemAuthor getRequestItemAuthor(Context context, Item item) + throws SQLException { + EPerson submitter = item.getSubmitter(); + RequestItemAuthor author = new RequestItemAuthor( + submitter.getFullName(), submitter.getEmail()); + return author; + } + +} 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/sfx/package-info.java b/dspace-api/src/main/java/org/dspace/app/sfx/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..6d74d406bdc98f96a6d8f1beaaf2ab7067e678e0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sfx/package-info.java @@ -0,0 +1,16 @@ +/** + * 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/ + */ + +/** + * <p>SFX/OpenURL link server support.</p> + * + * @see org.dspace.app.webui.jsptag.SFXLinkTag + * @see org.dspace.app.xmlui.aspect.artifactbrowser.ItemViewer + */ + +package org.dspace.app.sfx; diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAJournal.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAJournal.java new file mode 100644 index 0000000000000000000000000000000000000000..67f358b0429e9fbaf17bbae40bf4716cfdeb9606 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAJournal.java @@ -0,0 +1,56 @@ +/** + * 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.sherpa; + +/** + * POJO representation for a SHERPA journal + * + * @author Andrea Bollini + * + */ +public class SHERPAJournal +{ + private String title; + + private String issn; + + private String zetopub; + + private String romeopub; + + public SHERPAJournal(String title, String issn, String zetopub, + String romeopub) + { + super(); + this.title = title; + this.issn = issn; + this.zetopub = zetopub; + this.romeopub = romeopub; + } + + public String getTitle() + { + return title; + } + + public String getIssn() + { + return issn; + } + + public String getZetopub() + { + return zetopub; + } + + public String getRomeopub() + { + return romeopub; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAPublisher.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAPublisher.java new file mode 100644 index 0000000000000000000000000000000000000000..a1b4fd6add43fc24e3470d1435158cdafcaefc2c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAPublisher.java @@ -0,0 +1,183 @@ +/** + * 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.sherpa; + +import java.util.List; + +/** + * POJO representation for a SHERPA Publisher record + * + * @author Andrea Bollini + * + */ +public class SHERPAPublisher +{ + private String name; + + private String alias; + + private String homeurl; + + private String prearchiving; + + private List<String> prerestriction; + + private String postarchiving; + + private List<String> postrestriction; + + private String pubarchiving; + + private List<String> pubrestriction; + + private List<String> condition; + + private String paidaccessurl; + + private String paidaccessname; + + private String paidaccessnotes; + + private List<String[]> copyright; + + private String romeocolour; + + private String dateadded; + + private String dateupdated; + + public SHERPAPublisher(String name, String alias, String homeurl, + String prearchiving, List<String> prerestriction, + String postarchiving, List<String> postrestriction, + String pubarchiving, List<String> pubrestriction, + List<String> condition, String paidaccessurl, + String paidaccessname, String paidaccessnotes, + List<String[]> copyright, String romeocolour, String datedded, + String dateupdated) + { + this.name = name; + + this.alias = alias; + + this.homeurl = homeurl; + + this.prearchiving = prearchiving; + + this.prerestriction = prerestriction; + + this.postarchiving = postarchiving; + + this.postrestriction = postrestriction; + + this.pubarchiving = pubarchiving; + + this.pubrestriction = pubrestriction; + + this.condition = condition; + + this.paidaccessurl = paidaccessurl; + + this.paidaccessname = paidaccessname; + + this.paidaccessnotes = paidaccessnotes; + + this.copyright = copyright; + + this.romeocolour = romeocolour; + + this.dateadded = datedded; + + this.dateupdated = dateupdated; + } + + public String getName() + { + return name; + } + + public String getAlias() + { + return alias; + } + + public String getHomeurl() + { + return homeurl; + } + + public String getPrearchiving() + { + return prearchiving; + } + + public List<String> getPrerestriction() + { + return prerestriction; + } + + public String getPostarchiving() + { + return postarchiving; + } + + public List<String> getPostrestriction() + { + return postrestriction; + } + + public String getPubarchiving() + { + return pubarchiving; + } + + public List<String> getPubrestriction() + { + return pubrestriction; + } + + public List<String> getCondition() + { + return condition; + } + + public String getPaidaccessurl() + { + return paidaccessurl; + } + + public String getPaidaccessname() + { + return paidaccessname; + } + + public String getPaidaccessnotes() + { + return paidaccessnotes; + } + + public List<String[]> getCopyright() + { + return copyright; + } + + public String getRomeocolour() + { + return romeocolour; + } + + public String getDatedded() + { + return dateadded; + } + + public String getDateupdated() + { + return dateupdated; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAResponse.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..02a13dd6eb1f137377c18e7baf708f0eb6cedec1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAResponse.java @@ -0,0 +1,223 @@ +/** + * 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.sherpa; + +import java.io.InputStream; +import java.util.LinkedList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * JAVA representation for a SHERPA API Response + * + * @author Andrea Bollini + * + */ +public class SHERPAResponse +{ + private boolean error; + + private String message; + + private String license; + + private String licenseURL; + + private String disclaimer; + + private List<SHERPAJournal> journals; + + private List<SHERPAPublisher> publishers; + + public SHERPAResponse(InputStream xmlData) + { + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(xmlData); + + Element xmlRoot = inDoc.getDocumentElement(); + Element dataRoot = XMLUtils.getSingleElement(xmlRoot, "romeoapi"); + + Element headersElement = XMLUtils.getSingleElement(xmlRoot, + "header"); + Element journalsElement = XMLUtils.getSingleElement(xmlRoot, + "journals"); + Element publishersElement = XMLUtils.getSingleElement(xmlRoot, + "publishers"); + + message = XMLUtils.getElementValue(headersElement, "message"); + + if (StringUtils.isNotBlank(message)) + { + error = true; + return; + } + + license = XMLUtils.getElementValue(headersElement, "license"); + licenseURL = XMLUtils.getElementValue(headersElement, "licenseurl"); + disclaimer = XMLUtils.getElementValue(headersElement, "disclaimer"); + + List<Element> journalsList = XMLUtils.getElementList( + journalsElement, "journal"); + List<Element> publishersList = XMLUtils.getElementList( + publishersElement, "publisher"); + + if (journalsList != null) + { + journals = new LinkedList<SHERPAJournal>(); + for (Element journalElement : journalsList) + { + journals.add(new SHERPAJournal( + XMLUtils.getElementValue(journalElement, "jtitle"), + XMLUtils.getElementValue(journalElement, "issn"), + XMLUtils.getElementValue(journalElement, "zetopub"), + XMLUtils.getElementValue(journalElement, "romeopub"))); + } + } + + if (publishersList != null) + { + publishers = new LinkedList<SHERPAPublisher>(); + for (Element publisherElement : publishersList) + { + Element preprintsElement = XMLUtils.getSingleElement( + publisherElement, "preprints"); + Element preprintsRestrictionElement = XMLUtils + .getSingleElement(publisherElement, + "prerestrictions"); + + Element postprintsElement = XMLUtils.getSingleElement( + publisherElement, "postprints"); + Element postprintsRestrictionElement = XMLUtils + .getSingleElement(publisherElement, + "postrestrictions"); + + Element pdfversionElement = XMLUtils.getSingleElement( + publisherElement, "pdfversion"); + Element pdfversionRestrictionElement = XMLUtils + .getSingleElement(publisherElement, + "pdfrestrictions"); + + Element conditionsElement = XMLUtils.getSingleElement( + publisherElement, "conditions"); + Element paidaccessElement = XMLUtils.getSingleElement( + publisherElement, "paidaccess"); + + Element copyrightlinksElement = XMLUtils.getSingleElement( + publisherElement, "copyrightlinks"); + + publishers + .add(new SHERPAPublisher(XMLUtils.getElementValue( + publisherElement, "name"), + XMLUtils.getElementValue(publisherElement, + "alias"), XMLUtils.getElementValue( + publisherElement, "homeurl"), + + XMLUtils.getElementValue(preprintsElement, + "prearchiving"), + XMLUtils.getElementValueList( + preprintsRestrictionElement, + "prerestriction"), + + XMLUtils.getElementValue(postprintsElement, + "postarchiving"), + XMLUtils.getElementValueList( + postprintsRestrictionElement, + "postrestriction"), + + XMLUtils.getElementValue(pdfversionElement, + "pdfarchiving"), + XMLUtils.getElementValueList( + pdfversionRestrictionElement, + "pdfrestriction"), + + XMLUtils + .getElementValueList( + conditionsElement, + "condition"), XMLUtils + .getElementValue(paidaccessElement, + "paidaccessurl"), XMLUtils + .getElementValue(paidaccessElement, + "paidaccessname"), XMLUtils + .getElementValue(paidaccessElement, + "paidaccessnotes"), + XMLUtils.getElementValueArrayList( + copyrightlinksElement, + "copyrightlink", + "copyrightlinktext", + "copyrightlinkurl"), XMLUtils + .getElementValue(publisherElement, + "romeocolour"), XMLUtils + .getElementValue(publisherElement, + "dateadded"), XMLUtils + .getElementValue(publisherElement, + "dateupdated"))); + } + } + } + catch (Exception e) + { + error = true; + } + } + + public SHERPAResponse(String message) + { + this.message = message; + this.error = true; + } + + public boolean isError() + { + return error; + } + + public String getMessage() + { + return message; + } + + public String getLicense() + { + return license; + } + + public String getLicenseURL() + { + return licenseURL; + } + + public String getDisclaimer() + { + return disclaimer; + } + + public List<SHERPAJournal> getJournals() + { + return journals; + } + + public List<SHERPAPublisher> getPublishers() + { + return publishers; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java new file mode 100644 index 0000000000000000000000000000000000000000..6d45ad329c4cf38fef08ef4f215922f16896521a --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/SHERPAService.java @@ -0,0 +1,67 @@ +/** + * 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.sherpa; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.dspace.core.ConfigurationManager; + +public class SHERPAService +{ + public SHERPAResponse searchByJournalISSN(String query) + { + String endpoint = ConfigurationManager.getProperty("sherpa.romeo.url"); + String apiKey = ConfigurationManager.getProperty("sherpa.romeo.apikey"); + + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + method = new GetMethod(endpoint); + + NameValuePair id = new NameValuePair("issn", query); + NameValuePair versions = new NameValuePair("versions", "all"); + NameValuePair[] params = null; + if (StringUtils.isNotBlank(apiKey)) + { + NameValuePair ak = new NameValuePair("ak", apiKey); + params = new NameValuePair[] { id, versions, ak }; + } + else + { + params = new NameValuePair[] { id, versions }; + } + method.setQueryString(params); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + return new SHERPAResponse("SHERPA/RoMEO return not OK status: " + + statusCode); + } + + return new SHERPAResponse(method.getResponseBodyAsStream()); + } + catch (Exception e) + { + return new SHERPAResponse( + "Error processing the SHERPA/RoMEO answer"); + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/submit/ISSNItemExtractor.java b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/ISSNItemExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..f107c4d9a5ab789982eda402718c18932dafd52c --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/ISSNItemExtractor.java @@ -0,0 +1,18 @@ +/** + * 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.sherpa.submit; + +import java.util.List; + +import org.dspace.content.Item; +import org.dspace.core.Context; + +public interface ISSNItemExtractor +{ + public List<String> getISSNs(Context context, Item item); +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataAuthorityISSNExtractor.java b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataAuthorityISSNExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..0e34f391b88bb43b921ca6e040e4ff700f5d139e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataAuthorityISSNExtractor.java @@ -0,0 +1,40 @@ +/** + * 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.sherpa.submit; + +import java.util.ArrayList; +import java.util.List; + +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.core.Context; + +public class MetadataAuthorityISSNExtractor implements ISSNItemExtractor +{ + private List<String> metadataList; + + public void setMetadataList(List<String> metadataList) + { + this.metadataList = metadataList; + } + + @Override + public List<String> getISSNs(Context context, Item item) + { + List<String> values = new ArrayList<String>(); + for (String metadata : metadataList) + { + DCValue[] dcvalues = item.getMetadata(metadata); + for (DCValue dcvalue : dcvalues) + { + values.add(dcvalue.authority); + } + } + return values; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataValueISSNExtractor.java b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataValueISSNExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..bf7e52106eb317ba2894f28bb239f5849e1e80f9 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/MetadataValueISSNExtractor.java @@ -0,0 +1,40 @@ +/** + * 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.sherpa.submit; + +import java.util.ArrayList; +import java.util.List; + +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.core.Context; + +public class MetadataValueISSNExtractor implements ISSNItemExtractor +{ + private List<String> metadataList; + + public void setMetadataList(List<String> metadataList) + { + this.metadataList = metadataList; + } + + @Override + public List<String> getISSNs(Context context, Item item) + { + List<String> values = new ArrayList<String>(); + for (String metadata : metadataList) + { + DCValue[] dcvalues = item.getMetadata(metadata); + for (DCValue dcvalue : dcvalues) + { + values.add(dcvalue.value); + } + } + return values; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitConfigurationService.java b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitConfigurationService.java new file mode 100644 index 0000000000000000000000000000000000000000..071c4d03d1041ec0f2717d4435ed44488a789fbb --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitConfigurationService.java @@ -0,0 +1,25 @@ +/** + * 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.sherpa.submit; + +import java.util.List; + +public class SHERPASubmitConfigurationService +{ + private List<ISSNItemExtractor> issnItemExtractors; + + public void setIssnItemExtractors(List<ISSNItemExtractor> issnItemExtractors) + { + this.issnItemExtractors = issnItemExtractors; + } + + public List<ISSNItemExtractor> getIssnItemExtractors() + { + return issnItemExtractors; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitService.java b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitService.java new file mode 100644 index 0000000000000000000000000000000000000000..1cb033a403c026c420ced7865c30a0d878634b38 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/sherpa/submit/SHERPASubmitService.java @@ -0,0 +1,90 @@ +/** + * 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.sherpa.submit; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.sherpa.SHERPAResponse; +import org.dspace.app.sherpa.SHERPAService; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.core.LogManager; + +public class SHERPASubmitService +{ + private SHERPAService sherpaService; + + private SHERPASubmitConfigurationService configuration; + + /** log4j logger */ + private static Logger log = Logger.getLogger(SHERPASubmitService.class); + + public void setConfiguration(SHERPASubmitConfigurationService configuration) + { + this.configuration = configuration; + } + + public void setSherpaService(SHERPAService sherpaService) + { + this.sherpaService = sherpaService; + } + + public SHERPAResponse searchRelatedJournals(Context context, Item item) + { + Set<String> issns = getISSNs(context, item); + if (issns == null || issns.size() == 0) + { + return null; + } + else + { + return sherpaService.searchByJournalISSN(StringUtils.join(issns, ",")); + } + } + + private Set<String> getISSNs(Context context, Item item) + { + Set<String> issns = new LinkedHashSet<String>(); + if (configuration.getIssnItemExtractors() == null) + { + log.warn(LogManager.getHeader(context, "searchRelatedJournals", + "no issnItemExtractors defined")); + return null; + } + for (ISSNItemExtractor extractor : configuration.getIssnItemExtractors()) + { + List<String> eIssns = extractor.getISSNs(context, item); + if (eIssns != null) + { + for (String eIssn : eIssns) + { + issns.add(eIssn.trim()); + } + } + } + return issns; + } + + public boolean hasISSNs(Context context, Item item) + { + Set<String> issns = getISSNs(context, item); + if (issns == null || issns.size() == 0) + { + return false; + } + else + { + return true; + } + } + +} 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/AbstractDSpaceWebapp.java b/dspace-api/src/main/java/org/dspace/app/util/AbstractDSpaceWebapp.java new file mode 100644 index 0000000000000000000000000000000000000000..f73f3d24dc307102401476750309db2df688cfdf --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/AbstractDSpaceWebapp.java @@ -0,0 +1,191 @@ +/** + * 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.util; + +import java.io.IOException; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.HeadMethod; +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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Represent a DSpace application while it is running. This helps us report + * which applications *are* running, by exposing a record that can be viewed + * externally. + * + * @author mwood + */ +abstract public class AbstractDSpaceWebapp + implements DSpaceWebappMXBean +{ + private static final Logger log = LoggerFactory.getLogger(AbstractDSpaceWebapp.class); + + protected String kind; + + protected Date started; + + protected String url; + + private TableRow row; + + /** Prevent null instantiation. */ + protected AbstractDSpaceWebapp() + { + } + + /** + * Construct a particular kind of DSpace application. + * + * @param kind what kind of application is this? (XMLUI, JSPUI, etc.) + */ + public AbstractDSpaceWebapp(String kind) + { + this.kind = kind; + + started = new Date(); + + url = ConfigurationManager.getProperty("dspace.url"); + if (null == url) + { + throw new IllegalStateException("dspace.url is undefined"); + } + } + + /** Record that this application is running. */ + public void register() + { + // Create the database entry + Timestamp now = new Timestamp(started.getTime()); + try { + Context context = new Context(); + row = DatabaseManager.create(context, "Webapp"); + row.setColumn("AppName", kind); + row.setColumn("URL", url); + row.setColumn("Started", now); + row.setColumn("isUI", isUI() ? 1 : 0); // update won't widen boolean to integer + DatabaseManager.update(context, row); + context.complete(); + } catch (SQLException e) { + log.error("Failed to record startup in Webapp table.", e); + } + } + + /** Record that this application is not running. */ + public void deregister() + { + // Remove the database entry + try { + Context context = new Context(); + DatabaseManager.delete(context, row); + context.complete(); + } catch (SQLException e) { + log.error("Failed to record shutdown in Webapp table.", e); + } + } + + /** Return the list of running applications. */ + static public List<AbstractDSpaceWebapp> getApps() + { + ArrayList<AbstractDSpaceWebapp> apps = new ArrayList<AbstractDSpaceWebapp>(); + TableRowIterator tri; + + Context context = null; + HttpMethod request = null; + try { + context = new Context(); + tri = DatabaseManager.queryTable(context, "Webapp", + "SELECT * FROM Webapp"); + + for (TableRow row : tri.toList()) + { + DSpaceWebapp app = new DSpaceWebapp(); + app.kind = row.getStringColumn("AppName"); + app.url = row.getStringColumn("URL"); + app.started = row.getDateColumn("Started"); + app.uiQ = row.getBooleanColumn("isUI"); + + HttpClient client = new HttpClient(); + request = new HeadMethod(app.url); + int status = client.executeMethod(request); + request.getResponseBody(); + if (status != HttpStatus.SC_OK) + { + DatabaseManager.delete(context, row); + context.commit(); + continue; + } + + apps.add(app); + } + } catch (SQLException e) { + log.error("Unable to list running applications", e); + } catch (HttpException e) { + log.error("Failure checking for a running webapp", e); + } catch (IOException e) { + log.error("Failure checking for a running webapp", e); + } finally { + if (null != request) + { + request.releaseConnection(); + } + if (null != context) + { + context.abort(); + } + } + + return apps; + } + + /** Container for retrieved database rows. */ + static private class DSpaceWebapp + extends AbstractDSpaceWebapp + { + private boolean uiQ; + + @Override + public boolean isUI() + { + return uiQ; + } + } + + /* DSpaceWebappMXBean methods */ + + @Override + public String getKind() + { + return kind; + } + + @Override + public String getURL() + { + return url; + } + + @Override + public String getStarted() + { + return started.toString(); + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java b/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java new file mode 100644 index 0000000000000000000000000000000000000000..a6bb2e57dc10533495590f13755bcb0f4e53a2cb --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/CollectionDropDown.java @@ -0,0 +1,74 @@ +/** + * 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.util; + +import java.sql.SQLException; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.core.ConfigurationManager; + +/** + * Utility class for lists of collections. + */ + +public class CollectionDropDown { + + /** + * Get full path starting from a top-level community via subcommunities down to a collection. + * The full path will not be truncated. + * + * @param col + * Get full path for this collection + * @return Full path to the collection + */ + public static String collectionPath(Collection col) throws SQLException + { + return CollectionDropDown.collectionPath(col, 0); + } + + /** + * Get full path starting from a top-level community via subcommunities down to a collection. + * The full cat will be truncated to the specified number of characters and prepended with an ellipsis. + * + * @param col + * Get full path for this collection + * @param maxchars + * Truncate the full path to maxchar characters. 0 means do not truncate. + * @return Full path to the collection (truncated) + */ + public static String collectionPath(Collection col, int maxchars) throws SQLException + { + String separator = ConfigurationManager.getProperty("subcommunity.separator"); + if (separator == null) + { + separator = " > "; + } + + Community[] getCom = null; + StringBuffer name = new StringBuffer(""); + getCom = col.getCommunities(); // all communities containing given collection + for (Community com : getCom) + { + name.insert(0, com.getMetadata("name") + separator); + } + + name.append(col.getMetadata("name")); + + if (maxchars != 0) + { + int len = name.length(); + if (len > maxchars) + { + name = new StringBuffer(name.substring(len - (maxchars - 1), len)); + name.insert(0, "\u2026"); // prepend with an ellipsis (cut from left) + } + } + + return name.toString(); + } +} 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/DSpaceWebappMXBean.java b/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappMXBean.java new file mode 100644 index 0000000000000000000000000000000000000000..46c50b5744e21a544fa856267164032e1daed001 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/DSpaceWebappMXBean.java @@ -0,0 +1,29 @@ +/** + * 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.util; + +/** + * MBean type for discovering DSpace web applications. + * + * @author mwood + */ +public interface DSpaceWebappMXBean +{ + /** Is this webapp a user interface? False if machine interface such as SWORD. */ + public boolean isUI(); + + /** What kind of webapp? XMLUI, OAI, etc. */ + public String getKind(); + + /** What is the base URL of this application? */ + public String getURL(); + + /** When did this application start? */ + public String getStarted(); +} 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/app/util/Version.java b/dspace-api/src/main/java/org/dspace/app/util/Version.java new file mode 100644 index 0000000000000000000000000000000000000000..ad7cc685dcaae0a77b16de5b222789db8bed6b89 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/Version.java @@ -0,0 +1,105 @@ +/** + * 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.util; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import org.dspace.services.ConfigurationService; +import org.dspace.utils.DSpace; + +/** + * Display information about this DSpace, its environment, and how it was built. + * + * @author mwood + */ +public class Version +{ + public static void main(String[] argv) + throws IOException + { + InputStream propStream; + + Properties sys = System.getProperties(); + + // DSpace version + System.out.printf("DSpace version: %s\n", + Util.getSourceVersion()); + + // SCM revision + Properties scm = new Properties(); + propStream = Version.class.getResourceAsStream("/scm.properties"); + if (null != propStream) + { + scm.load(propStream); + } + System.out.printf(" SCM revision: %s\n", scm.get("revision")); + System.out.printf(" SCM branch: %s\n", scm.get("branch")); + + // OS version + System.out.printf(" OS: %s(%s) version %s\n", + sys.get("os.name"), + sys.get("os.arch"), + sys.get("os.version")); + + // UIs used + List<AbstractDSpaceWebapp> apps = AbstractDSpaceWebapp.getApps(); + System.out.println(" Applications:"); + for (AbstractDSpaceWebapp app : apps) + { + System.out.printf(" %s at %s\n", + app.getKind(), app.getURL()); + } + + // Is Discovery available? + ConfigurationService config = new DSpace().getConfigurationService(); + String consumers = config.getPropertyAsType("event.dispatcher.default.consumers", ""); // Avoid null pointer + List<String> consumerList = Arrays.asList(consumers.split("\\s*,\\s*")); + if (consumerList.contains("discovery")) + { + System.out.println(" Discovery: enabled."); + } + + // Is Lucene search enabled? + if (consumerList.contains("search")) + { + System.out.println(" Lucene search: enabled."); + } + + // Java version + System.out.printf(" JRE: %s version %s\n", + sys.get("java.vendor"), + sys.get("java.version")); + + // ant version + Properties ant = new Properties(); + propStream = Version.class.getResourceAsStream("/ant.properties"); + if (null != propStream) + { + ant.load(propStream); + } + System.out.printf(" Ant version: %s\n", + ant.get("ant.version")); + + // maven version + Properties maven = new Properties(); + propStream = Version.class.getResourceAsStream("/maven.properties"); + if (null != propStream) + { + maven.load(propStream); + } + System.out.printf(" Maven version: %s\n", + maven.get("maven.version")); + + // DSpace directory path + System.out.printf(" DSpace home: %s\n", + config.getProperty("dspace.dir")); + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..7089f884ab33edb172f68ca38f1a35d7bd0b88cc --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/XMLUtils.java @@ -0,0 +1,192 @@ +/** + * 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.util; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +/** + * Simple class to read information from small XML using DOM manipulation + * + * @author Andrea Bollini + * + */ +public class XMLUtils +{ + /** + * + * @param rootElement + * the starting node + * @param subElementName + * the name of the subelement to find + * @return the list of all DOM Element with the provided name direct child + * of the starting node + */ + public static List<Element> getElementList(Element dataRoot, String name) + { + NodeList list = dataRoot.getElementsByTagName(name); + List<Element> listElements = new ArrayList<Element>(); + for (int i = 0; i < list.getLength(); i++) + { + Element item = (Element) list.item(i); + if (item.getParentNode().equals(dataRoot)) + { + listElements.add(item); + } + } + return listElements; + } + + /** + * + * @param dataRoot + * the starting node + * @param name + * the name of the sub element + * @param attr + * the attribute to get + * @return the value of the attribute for the sub element with the specified + * name in the starting node + */ + public static String getElementAttribute(Element dataRoot, String name, + String attr) + { + Element element = getSingleElement(dataRoot, name); + String attrValue = null; + if (element != null) + { + attrValue = element.getAttribute(attr); + if (StringUtils.isNotBlank(attrValue)) + { + attrValue = attrValue.trim(); + } + else + attrValue = null; + } + return attrValue; + } + + /** + * + * @param dataRoot + * the starting node + * @param name + * the name of the sub element + * @return the text content of the sub element with the specified name in + * the starting node + */ + public static String getElementValue(Element dataRoot, String name) + { + Element element = getSingleElement(dataRoot, name); + String elementValue = null; + if (element != null) + { + elementValue = element.getTextContent(); + if (StringUtils.isNotBlank(elementValue)) + { + elementValue = elementValue.trim(); + } + else + elementValue = null; + } + return elementValue; + } + + /** + * Return the first element child with the specified name + * + * @param dataRoot + * the starting node + * @param name + * the name of sub element to look for + * @return the first child element or null if no present + */ + public static Element getSingleElement(Element dataRoot, String name) + { + List<Element> nodeList = getElementList(dataRoot, name); + Element element = null; + if (nodeList != null && nodeList.size() > 0) + { + element = (Element) nodeList.get(0); + } + return element; + } + + /** + * + * @param rootElement + * the starting node + * @param subElementName + * the name of the subelement to find + * @return a list of string including all the text contents of the sub + * element with the specified name. If there are not sub element + * with the supplied name the method will return null + */ + public static List<String> getElementValueList(Element rootElement, + String subElementName) + { + if (rootElement == null) + return null; + + List<Element> subElements = getElementList(rootElement, subElementName); + if (subElements == null) + return null; + + List<String> result = new LinkedList<String>(); + for (Element el : subElements) + { + if (StringUtils.isNotBlank(el.getTextContent())) + { + result.add(el.getTextContent().trim()); + } + } + return result; + } + + /** + * root/subElement[]/field1, field2, fieldN + * + * @param rootElement + * the starting node + * @param subElementName + * the name of the sub element to work on + * @param fieldsName + * the names of the sub-sub-elements from which get the text + * content + * @return a list of array strings. The length of the array is equals to the + * number of fields required. For any fields the first textual value + * found in the sub element is used, null if no value is present + */ + public static List<String[]> getElementValueArrayList(Element rootElement, + String subElementName, String... fieldsName) + { + if (rootElement == null) + return null; + + List<Element> subElements = getElementList(rootElement, subElementName); + if (subElements == null) + return null; + + List<String[]> result = new LinkedList<String[]>(); + for (Element el : subElements) + { + String[] tmp = new String[fieldsName.length]; + for (int idx = 0; idx < fieldsName.length; idx++) + { + tmp[idx] = XMLUtils.getElementValue(el, fieldsName[idx]); + } + result.add(tmp); + } + return result; + } +} \ No newline at end of file diff --git a/dspace-api/src/main/java/org/dspace/app/util/package-info.java b/dspace-api/src/main/java/org/dspace/app/util/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..faf86e72892ee61fa6db879cf977169b84451edf --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/app/util/package-info.java @@ -0,0 +1,15 @@ +/** + * 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/ + */ + +/** + * <p>Miscellaneous utility classes. Includes supporting classes for AuthorizeManager, input forms, submission process, webapp init/cleanup, Google Scholar metadata, metadata visibility, OpenSearch, syndication feeds and more.</p> + * + */ + +package org.dspace.app.util; + 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/ItemCountDAOSolr.java b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java new file mode 100644 index 0000000000000000000000000000000000000000..890bf0c926768eafa7b5169ee86b4484581c9385 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOSolr.java @@ -0,0 +1,189 @@ +/** + * 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.browse; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.discovery.DiscoverFacetField; +import org.dspace.discovery.DiscoverQuery; +import org.dspace.discovery.DiscoverResult; +import org.dspace.discovery.DiscoverResult.FacetResult; +import org.dspace.discovery.SearchService; +import org.dspace.discovery.SearchServiceException; +import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; +import org.dspace.utils.DSpace; + +/** + * Discovery (Solr) driver implementing ItemCountDAO interface to look up item + * count information in communities and collections. Caching operations are + * intentionally not implemented because Solr already is our cache. + * + * @author Ivan Masár, Andrea Bollini + * + */ +public class ItemCountDAOSolr implements ItemCountDAO +{ + /** Log4j logger */ + private static Logger log = Logger.getLogger(ItemCountDAOSolr.class); + + /** DSpace context */ + private Context context; + + /** + * Hold the communities item count obtained from SOLR after the first query. This only works + * well if the ItemCountDAO lifecycle is bound to the request lifecycle as + * it is now. If we switch to a Spring-based instantiation we should mark + * this bean as prototype + **/ + private Map<String, Integer> communitiesCount = null; + + /** Hold the collection item count obtained from SOLR after the first query **/ + private Map<String, Integer> collectionsCount = null; + + /** DSpace helper services access object */ + DSpace dspace = new DSpace(); + + /** Solr search service */ + SearchService searcher = dspace.getServiceManager().getServiceByName(SearchService.class.getName(), SearchService.class); + + /** + * Throw an ItemCountException as caching is not supported by ItemCountDAOSolr. + * + * @param collection + * @param count + * @throws ItemCountException + */ + public void collectionCount(Collection collection, int count) throws ItemCountException + { + throw new ItemCountException("Caching is not supported by the ItemCountDAOSolr as it is not really needed, Solr is faster!"); + } + + /** + * Throw an ItemCountException as caching is not supported by ItemCountDAOSolr. + * + * @param community + * @param count + * @throws ItemCountException + */ + public void communityCount(Community community, int count) throws ItemCountException + { + throw new ItemCountException("Caching is not supported by the ItemCountDAOSolr as it is not really needed, Solr is faster!"); + } + + /** + * Set the dspace context to use + * + * @param context + * @throws ItemCountException + */ + public void setContext(Context context) throws ItemCountException + { + this.context = context; + } + + /** + * Get the count of the items in the given container. + * + * @param dso + * @throws ItemCountException + */ + public int getCount(DSpaceObject dso) throws ItemCountException + { + loadCount(); + DiscoverQuery query = new DiscoverQuery(); + Integer val = null; + if (dso instanceof Collection) + { + val = collectionsCount.get(String.valueOf(((Collection) dso).getID())); + } + else if (dso instanceof Community) + { + val = communitiesCount.get(String.valueOf(((Community) dso).getID())); + } + else + { + throw new ItemCountException("We can only count items in Communities or Collections"); + } + + if (val != null) + { + return val.intValue(); + } + else + { + return 0; + } + } + + /** + * remove the cache for the given container (does nothing in the Solr backend) + * + * @param dso + * @throws ItemCountException + */ + public void remove(DSpaceObject dso) throws ItemCountException + { + } + + /** + * make sure that the counts are actually fetched from Solr (if haven't been + * cached in a Map yet) + * + * @throws ItemCountException + */ + private void loadCount() throws ItemCountException + { + if (communitiesCount != null || collectionsCount != null) + { + return; + } + + communitiesCount = new HashMap<String, Integer>(); + collectionsCount = new HashMap<String, Integer>(); + + DiscoverQuery query = new DiscoverQuery(); + query.setFacetMinCount(1); + query.addFacetField(new DiscoverFacetField("location.comm", + DiscoveryConfigurationParameters.TYPE_STANDARD, -1, + DiscoveryConfigurationParameters.SORT.COUNT)); + query.addFacetField(new DiscoverFacetField("location.coll", + DiscoveryConfigurationParameters.TYPE_STANDARD, -1, + DiscoveryConfigurationParameters.SORT.COUNT)); + query.addFilterQueries("search.resourcetype:2"); // count only items + query.addFilterQueries("NOT(discoverable:false)"); // only discoverable + query.setMaxResults(0); + + DiscoverResult sResponse = null; + try + { + sResponse = searcher.search(context, query, false); + List<FacetResult> commCount = sResponse.getFacetResult("location.comm"); + List<FacetResult> collCount = sResponse.getFacetResult("location.coll"); + for (FacetResult c : commCount) + { + communitiesCount.put(c.getAsFilterQuery(),(int) c.getCount()); + } + for (FacetResult c : collCount) + { + collectionsCount.put(c.getAsFilterQuery(),(int) c.getCount()); + } + } + catch (SearchServiceException e) + { + log.error("caught exception: ", e); + throw new ItemCountException(e); + } + } +} 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/core/LicenseManager.java b/dspace-api/src/main/java/org/dspace/core/LicenseManager.java new file mode 100644 index 0000000000000000000000000000000000000000..d9c59549eb0a364437d13b94c61208f4386877d8 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/LicenseManager.java @@ -0,0 +1,211 @@ +/** + * 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.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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Encapsulate the deposit license. + * + * @author mhwood + */ +public class LicenseManager +{ + private static final Logger log = LoggerFactory.getLogger(LicenseManager.class); + + /** The default license */ + private static String license; + + /** + * Writes license to a text file. + * + * @param licenseFile + * name for the file into which license will be written, + * relative to the current directory. + */ + public static void writeLicenseFile(String licenseFile, + String newLicense) + { + try + { + 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) + { + log.warn("license_write: " + e.getLocalizedMessage()); + } + license = newLicense; + } + + /** + * Get the License + * + * @param + * licenseFile file name + * + * @return + * license text + * + */ + public static String getLicenseText(String licenseFile) + { + InputStream is = null; + InputStreamReader ir = null; + BufferedReader br = null; + try + { + is = new FileInputStream(licenseFile); + ir = new InputStreamReader(is, "UTF-8"); + br = new BufferedReader(ir); + String lineIn; + license = ""; + while ((lineIn = br.readLine()) != null) + { + license = license + lineIn + '\n'; + } + } catch (IOException e) + { + log.error("Can't load configuration", e); + throw new IllegalStateException("Failed to read default license.", e); + } finally + { + if (br != null) + { + try + { + br.close(); + } catch (IOException ioe) + { + } + } + if (ir != null) + { + try + { + ir.close(); + } + catch (IOException ioe) + { + } + } + if (is != null) + { + try + { + is.close(); + } catch (IOException ioe) + { + } + } + } + return license; + } + + /** + * Get the site-wide default license that submitters need to grant + * + * @return the default license + */ + public static String getDefaultSubmissionLicense() + { + if (null == license) + { + init(); + } + return license; + } + + /** + * Load in the default license. + */ + private static void init() + { + File licenseFile = new File(ConfigurationManager.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; + LicenseManager.license = ""; + + while ((lineIn = br.readLine()) != null) + { + LicenseManager.license = LicenseManager.license + lineIn + '\n'; + } + + br.close(); + + } + catch (IOException e) + { + log.error("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) + { + try + { + fir.close(); + } + catch (IOException ioe) + { + } + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/core/NewsManager.java b/dspace-api/src/main/java/org/dspace/core/NewsManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e6128badd0b765b5f216e3234910c83c7f9e7728 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/core/NewsManager.java @@ -0,0 +1,116 @@ +/** + * 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.core; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Encapsulate access to the news texts. + * + * @author mhwood + */ +public class NewsManager +{ + private static final Logger log = LoggerFactory.getLogger(NewsManager.class); + + /** Not instantiable. */ + private NewsManager() {} + + /** + * 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(); + ir.close(); + fir.close(); + } + catch (IOException e) + { + log.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) + { + log.warn("news_write: " + e.getLocalizedMessage()); + } + + return news; + } + + /** + * Get the path for the news files. + * + */ + public static String getNewsFilePath() + { + String filePath = ConfigurationManager.getProperty("dspace.dir") + + File.separator + "config" + File.separator; + + return filePath; + } +} 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/ctask/general/MetadataWebService.java b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java new file mode 100644 index 0000000000000000000000000000000000000000..e58e83f0c4c347f24921fae4b618de02ad73453f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataWebService.java @@ -0,0 +1,543 @@ +/** + * 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.ctask.general; + +import java.io.InputStream; +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.namespace.NamespaceContext; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFactory; +import javax.xml.XMLConstants; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.HttpStatus; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import org.xml.sax.SAXException; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.curate.AbstractCurationTask; +import org.dspace.curate.Curator; +import org.dspace.curate.Mutative; +import org.dspace.curate.Suspendable; + +/** + * MetadataWebService task calls a web service using metadata from + * passed item to obtain data. Depending on configuration, this + * data may be assigned to item metadata fields, or just recorded in the + * task result string. Task succeeds if web service call succeeds and + * configured updates occur, fails if task user not authorized or item + * lacks metadata to call service, and returns error in all other cases + * (except skip status for non-item objects). + * Intended use: cataloging tool in workflow and general curation. + * The task uses a URL 'template' to compose the service call, e.g. + * + * http://www.sherpa.ac.uk/romeo/api29.php?issn={dc.identifier.issn} + * + * Task will substitute the value of the passed item's metadata field + * in the {parameter} position. If multiple values are present in the + * item field, the first value is used. + * + * The task uses another property (the datamap) to determine what data + * to extract from the service response and how to use it, e.g. + * + * //publisher/name=>dc.publisher,//romeocolour + * + * Task will evaluate the left-hand side (or entire token) of each + * comma-separated token in the property as an XPath 1.0 expression into + * the response document, and if there is a mapping symbol (e.g.'=>') and + * value, it will assign the response document value(s) to the named + * metadata field in the passed item. If the response document contains + * multiple values, they will all be assigned to the item field. The + * mapping symbol governs the nature of metadata field assignment: + * + * '->' mapping will add to any existing values in the item field + * '=>' mapping will replace any existing values in the item field + * '~>' mapping will add *only* if item field has no existing values + * + * Unmapped data (without a mapping symbol) will simply be added to the task + * result string, prepended by the XPath expression (a little prettified). + * Each label/value pair in the result string is separated by a space, + * unless the optional 'separator' property is defined. + * + * A very rudimentary facility for transformation of data is supported, e.g. + * + * http://www.crossref.org/openurl/?id={doi:dc.relation.isversionof}&format=unixref + * + * The 'doi:' prefix will cause the task to look for a 'transform' with that + * name, which is applied to the metadata value before parameter substitution + * occurs. Transforms are defined in a task property such as the following: + * + * transform.doi = match 10. trunc 60 + * + * This means exclude the value string up to the occurrence of '10.', then + * truncate after 60 characters. The only transform functions currently defined: + * + * 'cut' <number> = remove number leading characters + * 'trunc' <number> = remove trailing characters after number length + * 'match' <pattern> = start match at pattern + * 'text' <characters> = append literal characters (enclose in ' ' when whitespace needed) + * + * If the transform results in an invalid state (e.g. cutting more characters + * than are in the value), the condition will be logged and the + * un-transformed value used. + * + * Transforms may also be used in datamaps, e.g. + * + * //publisher/name=>shorten:dc.publisher,//romeocolour + * + * which would apply the 'shorten' transform to the service response value(s) + * prior to metadata field assignment. + * + * An optional property 'headers' may be defined to stipulate any HTTP headers + * required in the service call. The property syntax is double-pipe separated headers: + * + * Accept: text/xml||Cache-Control: no-cache + * + * @author richardrodgers + */ +@Mutative +@Suspendable +public class MetadataWebService extends AbstractCurationTask implements NamespaceContext +{ + /** log4j category */ + private static final Logger log = Logger.getLogger(MetadataWebService.class); + // transform token parsing pattern + private static Pattern ttPattern = Pattern.compile("\'([^\']*)\'|(\\S+)"); + // URL of web service with template parameters + private String urlTemplate = null; + // template parameter + private String templateParam = null; + // Item metadata field to use in service call + private String lookupField = null; + // Optional transformation of lookupField + private String lookupTransform = null; + // response data to map/record + private List<DataInfo> dataList = null; + // response document parsing tools + private DocumentBuilder docBuilder = null; + // language for metadata fields assigned + private String lang = null; + // field separator in result string + private String fieldSeparator = null; + // optional XML namespace map + private Map<String, String> nsMap = new HashMap<String, String>(); + // optional HTTP headers + private Map<String, String> headers = new HashMap<String, String>(); + + /** + * Initializes task + * @param curator Curator object performing this task + * @param taskId the configured local name of the task + */ + @Override + public void init(Curator curator, String taskId) throws IOException { + super.init(curator, taskId); + lang = ConfigurationManager.getProperty("default.language"); + String fldSep = taskProperty("separator"); + fieldSeparator = (fldSep != null) ? fldSep : " "; + urlTemplate = taskProperty("template"); + templateParam = urlTemplate.substring(urlTemplate.indexOf("{") + 1, + urlTemplate.indexOf("}")); + String[] parsed = parseTransform(templateParam); + lookupField = parsed[0]; + lookupTransform = parsed[1]; + dataList = new ArrayList<DataInfo>(); + for (String entry : taskProperty("datamap").split(",")) { + entry = entry.trim(); + String src = entry; + String mapping = null; + String field = null; + int mapIdx = getMapIndex(entry); + if (mapIdx > 0) { + src = entry.substring(0, mapIdx); + mapping = entry.substring(mapIdx, mapIdx + 2); + field = entry.substring(mapIdx + 2); + } + int slIdx = src.lastIndexOf("/"); + String label = (slIdx > 0) ? src.substring(slIdx + 1) : src; + dataList.add(new DataInfo(src, label, mapping, field)); + } + String hdrs = taskProperty("headers"); + if (hdrs != null) { + for (String header : hdrs.split("\\|\\|")) { + int split = header.indexOf(":"); + headers.put(header.substring(0, split).trim(), header.substring(split + 1).trim()); + } + } + // initialize response document parser + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + try { + docBuilder = factory.newDocumentBuilder(); + } catch (ParserConfigurationException pcE) { + log.error("caught exception: " + pcE); + // no point in continuing + throw new IOException(pcE.getMessage(), pcE); + } + } + + /** + * Perform the curation task upon passed DSO + * + * @param dso the DSpace object + * @throws IOException + */ + @Override + public int perform(DSpaceObject dso) throws IOException { + + int status = Curator.CURATE_SKIP; + StringBuilder resultSb = new StringBuilder(); + + if (dso.getType() == Constants.ITEM) { + Item item = (Item)dso; + String itemId = item.getHandle(); + if (itemId == null) { + // we are still in workflow - no handle assigned - try title + DCValue[] titleDc = item.getMetadata("dc", "title", null, Item.ANY); + String title = (titleDc.length > 0) ? titleDc[0].value : "untitled - dbId: " + item.getID(); + itemId = "Workflow item: " + title; + } else { + itemId = "handle: " + itemId; + } + resultSb.append(itemId); + // Only proceed if item has a value for service template parameter + DCValue[] dcVals = item.getMetadata(lookupField); + if (dcVals.length > 0 && dcVals[0].value.length() > 0) { + String value = transform(dcVals[0].value, lookupTransform); + status = callService(value, item, resultSb); + } else { + resultSb.append(" lacks metadata value required for service: ").append(lookupField); + status = Curator.CURATE_FAIL; + } + } else { + resultSb.append("Object skipped"); + } + report(resultSb.toString()); + setResult(resultSb.toString()); + return status; + } + + private int callService(String value, Item item, StringBuilder resultSb) throws IOException { + + String callUrl = urlTemplate.replaceAll("\\{" + templateParam + "\\}", value); + HttpClient client = new DefaultHttpClient(); + HttpGet req = new HttpGet(callUrl); + for (Map.Entry<String, String> entry : headers.entrySet()) { + req.addHeader(entry.getKey(), entry.getValue()); + } + HttpResponse resp = client.execute(req); + int status = Curator.CURATE_ERROR; + int statusCode = resp.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK) { + HttpEntity entity = resp.getEntity(); + if (entity != null) { + // boiler-plate handling taken from Apache 4.1 javadoc + InputStream instream = entity.getContent(); + try { + Document doc = docBuilder.parse(instream); + status = processResponse(doc, item, resultSb); + } catch (SAXException saxE) { + log.error("caught exception: " + saxE); + resultSb.append(" unable to read response document"); + } catch (RuntimeException ex) { + // In case of an unexpected exception you may want to abort + // the HTTP request in order to shut down the underlying + // connection and release it back to the connection manager. + req.abort(); + log.error("caught exception: " + ex); + throw ex; + } finally { + // Closing the input stream will trigger connection release + instream.close(); + } + // When HttpClient instance is no longer needed, + // shut down the connection manager to ensure + // immediate deallocation of all system resources + client.getConnectionManager().shutdown(); + } else { + log.error(" obtained no valid service response"); + resultSb.append("no service response"); + } + } else { + log.error("service returned non-OK status: " + statusCode); + resultSb.append("no service response"); + } + return status; + } + + private int processResponse(Document doc, Item item, StringBuilder resultSb) throws IOException { + boolean update = false; + int status = Curator.CURATE_ERROR; + List<String> values = new ArrayList<String>(); + checkNamespaces(doc); + try { + for (DataInfo info : dataList) { + NodeList nodes = (NodeList)info.expr.evaluate(doc, XPathConstants.NODESET); + values.clear(); + // if data found and we are mapping, check assignment policy + if (nodes.getLength() > 0 && info.mapping != null) { + if ("=>".equals(info.mapping)) { + item.clearMetadata(info.schema, info.element, info.qualifier, Item.ANY); + } else if ("~>".equals(info.mapping)) { + if (item.getMetadata(info.schema, info.element, info.qualifier, Item.ANY).length > 0) { + // there are values, so don't overwrite + continue; + } + } else { + for (DCValue dcVal : item.getMetadata(info.schema, info.element, info.qualifier, Item.ANY)) { + values.add(dcVal.value); + } + } + } + for (int i = 0; i < nodes.getLength(); i++) { + Node node = nodes.item(i); + String tvalue = transform(node.getFirstChild().getNodeValue(), info.transform); + // assign to metadata field if mapped && not present + if (info.mapping != null && ! values.contains(tvalue)) { + item.addMetadata(info.schema, info.element, info.qualifier, lang, tvalue); + update = true; + } + // add to result string in any case + resultSb.append(fieldSeparator).append(info.label).append(": ").append(tvalue); + } + } + // update Item if it has changed + if (update) { + item.update(); + } + status = Curator.CURATE_SUCCESS; + } catch (AuthorizeException authE) { + log.error("caught exception: " + authE); + resultSb.append(" not authorized to update"); + status = Curator.CURATE_FAIL; + } catch (SQLException sqlE) { + log.error("caught exception: " + sqlE); + resultSb.append(" error updating metadata"); + } catch (XPathExpressionException xpeE) { + log.error("caught exception: " + xpeE); + resultSb.append(" error reading response document"); + } + return status; + } + + private String transform(String value, String transDef) { + if (transDef == null) { + return value; + } + String[] tokens = tokenize(transDef); + String retValue = value; + for (int i = 0; i < tokens.length; i+= 2) { + if ("cut".equals(tokens[i]) || "trunc".equals(tokens[i])) { + int index = Integer.parseInt(tokens[i+1]); + if (retValue.length() > index) { + if ("cut".equals(tokens[i])) { + retValue = retValue.substring(index); + } else { + retValue = retValue.substring(0, index); + } + } else if ("cut".equals(tokens[i])) { + log.error("requested cut: " + index + " exceeds value length"); + return value; + } + } else if ("match".equals(tokens[i])) { + int index2 = retValue.indexOf(tokens[i+1]); + if (index2 > 0) { + retValue = retValue.substring(index2); + } else { + log.error("requested match: " + tokens[i+1] + " failed"); + return value; + } + } else if ("text".equals(tokens[i])) { + retValue = retValue + tokens[i+1]; + } else { + log.error(" unknown transform operation: " + tokens[i]); + return value; + } + } + return retValue; + } + + private String[] tokenize(String text) { + List<String> list = new ArrayList<String>(); + Matcher m = ttPattern.matcher(text); + while (m.find()) { + if (m.group(1) != null) { + list.add(m.group(1)); + } else if (m.group(2) != null) { + list.add(m.group(2)); + } + } + return list.toArray(new String[0]); + } + + private int getMapIndex(String mapping) { + int index = mapping.indexOf("->"); + if (index == -1) { + index = mapping.indexOf("=>"); + } + if (index == -1) { + index = mapping.indexOf("~>"); + } + return index; + } + + private String[] parseTransform(String field) { + String[] parsed = new String[2]; + parsed[0] = field; + int txIdx = field.indexOf(":"); + if (txIdx > 0) { + // transform specified + String txName = field.substring(0, txIdx); + parsed[1] = taskProperty("transform." + txName); + if (parsed[1] == null) { + log.error("no transform found for: " + txName); + } + parsed[0] = field.substring(txIdx + 1); + } + return parsed; + } + + private void checkNamespaces(Document document) throws IOException { + // skip if already done + if (dataList.get(0).expr != null) { + return; + } + try { + XPath xpath = XPathFactory.newInstance().newXPath(); + String prefix = null; + NamedNodeMap attrs = document.getDocumentElement().getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Node n = attrs.item(i); + String name = n.getNodeName(); + // remember if a namespace + if (name.startsWith("xmlns")) { + if (! "xmlns".equals(name)) { + // it is a declared (non-default) namespace - capture prefix + nsMap.put(name.substring(name.indexOf(":") + 1), n.getNodeValue()); + } else { + // it is the default name space - mint a unique prefix + prefix = "pre"; + nsMap.put(prefix, n.getNodeValue()); + } + } + } + if (nsMap.size() > 0) { + xpath.setNamespaceContext(this); + } + // now compile the XPath expressions + for (DataInfo info : dataList) { + info.expr = xpath.compile(mangleExpr(info.xpsrc, prefix)); + } + } catch (XPathExpressionException xpeE) { + log.error("caught exception: " + xpeE); + // no point in continuing + throw new IOException(xpeE.getMessage(), xpeE); + } + } + + private String mangleExpr(String expr, String prefix) { + if (prefix == null) { + return expr; + } + // OK the drill is to prepend all node names with the prefix + // *unless* the node name already has a prefix. + StringBuilder sb = new StringBuilder(); + int i = 0; + while (i < expr.length()) { + if (expr.charAt(i) == '/') { + sb.append("/"); + i++; + } else { + int next = expr.indexOf("/", i); + String token = (next > 0) ? expr.substring(i, next) : expr.substring(i); + if (! token.startsWith("@") && token.indexOf(":") < 0) { + sb.append(prefix).append(":"); + } + sb.append(token); + i += token.length(); + } + } + return sb.toString(); + } + + // ---- NamespaceContext methods ---- // + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new NullPointerException("Null prefix"); + } else if ("xml".equals(prefix)) { + return XMLConstants.XML_NS_URI; + } + String nsURI = nsMap.get(prefix); + return (nsURI != null) ? nsURI : XMLConstants.NULL_NS_URI; + } + + public String getPrefix(String uri) { + throw new UnsupportedOperationException(); + } + + public Iterator getPrefixes(String uri) { + throw new UnsupportedOperationException(); + } + + private class DataInfo { + public XPathExpression expr; // compiled XPath espression for data + public String xpsrc; // uncompiled XPath expression + public String label; // label for data in result string + public String mapping; // data mapping symbol: ->,=>,~>, or null = unmapped + public String schema; // item metadata field mapping target, null = unmapped + public String element; // item metadata field mapping target, null = unmapped + public String qualifier; // item metadata field mapping target, null = unmapped + public String transform; // optional transformation of data before field assignment + + public DataInfo(String xpsrc, String label, String mapping, String field) { + this.xpsrc = xpsrc; + this.expr = expr; + this.label = label; + this.mapping = mapping; + if (field != null) { + String[] parsed = parseTransform(field); + String[] parts = parsed[0].split("\\."); + this.schema = parts[0]; + this.element = parts[1]; + this.qualifier = (parts.length == 3) ? parts[2] : null; + this.transform = parsed[1]; + } + } + } +} 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/SolrServiceSpellIndexingPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java new file mode 100644 index 0000000000000000000000000000000000000000..d81b999cfe9f7da1e4e6da64f006a0013e938ad4 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceSpellIndexingPlugin.java @@ -0,0 +1,36 @@ +/** + * 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.discovery; + +import org.apache.solr.common.SolrInputDocument; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Context; + +/** + * Created with IntelliJ IDEA. + * User: kevin + * Date: 03/10/13 + * Time: 15:06 + * To change this template use File | Settings | File Templates. + */ +public class SolrServiceSpellIndexingPlugin implements SolrServiceIndexPlugin { + + @Override + public void additionalIndex(Context context, DSpaceObject dso, SolrInputDocument document) { + if(dso instanceof Item){ + DCValue[] dcValues = ((Item) dso).getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); + for (DCValue dcValue : dcValues) { + document.addField("a_spell", dcValue.value); + + } + } + + } +} 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/handle/MultiRemoteDSpaceRepositoryHandlePlugin.java b/dspace-api/src/main/java/org/dspace/handle/MultiRemoteDSpaceRepositoryHandlePlugin.java new file mode 100644 index 0000000000000000000000000000000000000000..2d57b8819e9b2286a6f7e395a6af1dcf6066da4e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/handle/MultiRemoteDSpaceRepositoryHandlePlugin.java @@ -0,0 +1,734 @@ +/** + * 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.handle; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import net.handle.hdllib.Encoder; +import net.handle.hdllib.HandleException; +import net.handle.hdllib.HandleStorage; +import net.handle.hdllib.HandleValue; +import net.handle.hdllib.ScanCallback; +import net.handle.hdllib.Util; +import net.handle.util.StreamTable; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import java.util.Iterator; + +/** + * Extension to the CNRI Handle Server that translates requests to resolve + * handles into remote calls to the mini-DSpace Handle resolver JSON API. This + * only provides some of the functionality (namely, the resolving of handles to + * URLs) of the CNRI HandleStorage interface. + * + * <p> + * This class is intended to be embedded in the CNRI Handle Server. It conforms + * to the HandleStorage interface that was delivered with Handle Server version + * 6.2.0. + * </p> + * + * @author Andrea Bollini + */ +public class MultiRemoteDSpaceRepositoryHandlePlugin implements HandleStorage +{ + /** + * Name of configuration file. This can be overwritten by setting a path + * to the configuration file to use in the system property + * <code>dspace.handle.plugin.configuration</code>. + */ + private static String CONFIG_FILE_NAME = "handle-dspace-plugin.cfg"; + /** + * Every Property starting with this key will be used as DSpace endpoint + * while resolving handles, f.e. http://localhost:8080/xmlui/handleresolver. + */ + private static String PROPERTY_KEY = "dspace.handle.endpoint"; + + /** log4j category */ + private static Logger log = Logger + .getLogger(MultiRemoteDSpaceRepositoryHandlePlugin.class); + + // maps prefixes to URLs from DSpace instances + private Map<String, String> prefixes; + + /** + * Constructor + */ + public MultiRemoteDSpaceRepositoryHandlePlugin() + { + } + + // ////////////////////////////////////// + // Non-Resolving methods -- unimplemented + // ////////////////////////////////////// + + /** + * HandleStorage interface method - not implemented. + */ + public void init(StreamTable st) throws Exception + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called init"); + } + + // initalize our prefix map + this.prefixes = new HashMap<String, String>(); + + // try to find our configuration + Properties properties = loadProperties(CONFIG_FILE_NAME); + + // find urls of all configured dspace instances + for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) + { + String propertyName = (String) e.nextElement(); + if (propertyName.startsWith(this.PROPERTY_KEY)) + { + // load the prefixes of this instance + loadPrefixes(properties.getProperty(propertyName)); + } + } + + // did we found any prefixes? + if (this.prefixes.isEmpty()) + { + throw new HandleException(HandleException.INTERNAL_ERROR, + "Unable to find configuration or to reach any DSpace instance."); + } + + if (log.isInfoEnabled()) + { + for (Iterator<String> it = this.prefixes.keySet().iterator(); it.hasNext() ;) + { + String prefix = it.next(); + log.info("Loaded Prefix " + prefix + " from " + this.prefixes.get(prefix)); + } + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void setHaveNA(byte[] theHandle, boolean haveit) + throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called setHaveNA (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void createHandle(byte[] theHandle, HandleValue[] values) + throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called createHandle (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public boolean deleteHandle(byte[] theHandle) throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called deleteHandle (not implemented)"); + } + + return false; + } + + /** + * HandleStorage interface method - not implemented. + */ + public void updateValue(byte[] theHandle, HandleValue[] values) + throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called updateValue (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void deleteAllRecords() throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called deleteAllRecords (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void checkpointDatabase() throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called checkpointDatabase (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void shutdown() + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called shutdown (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void scanHandles(ScanCallback callback) throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called scanHandles (not implemented)"); + } + } + + /** + * HandleStorage interface method - not implemented. + */ + public void scanNAs(ScanCallback callback) throws HandleException + { + // Not implemented + if (log.isInfoEnabled()) + { + log.info("Called scanNAs (not implemented)"); + } + } + + // ////////////////////////////////////// + // Resolving methods + // ////////////////////////////////////// + + /** + * Return the raw values for this handle. This implementation returns a + * single URL value. + * + * @param theHandle + * byte array representation of handle + * @param indexList + * ignored + * @param typeList + * ignored + * @return A byte array with the raw data for this handle. Currently, this + * consists of a single URL value. + * @exception HandleException + * If an error occurs while calling the Handle API. + */ + public byte[][] getRawHandleValues(byte[] theHandle, int[] indexList, + byte[][] typeList) throws HandleException + { + if (log.isInfoEnabled()) + { + log.info("Called getRawHandleValues"); + } + + if (theHandle == null) + { + throw new HandleException(HandleException.INTERNAL_ERROR); + } + + String handle = Util.decodeString(theHandle); + String url = getRemoteDSpaceURL(handle); + HandleValue value = new HandleValue(); + + value.setIndex(100); + value.setType(Util.encodeString("URL")); + value.setData(Util.encodeString(url)); + value.setTTLType((byte) 0); + value.setTTL(100); + value.setTimestamp(100); + value.setReferences(null); + value.setAdminCanRead(true); + value.setAdminCanWrite(false); + value.setAnyoneCanRead(true); + value.setAnyoneCanWrite(false); + + List<HandleValue> values = new LinkedList<HandleValue>(); + + values.add(value); + + byte[][] rawValues = new byte[values.size()][]; + + for (int i = 0; i < values.size(); i++) + { + HandleValue hvalue = values.get(i); + + rawValues[i] = new byte[Encoder.calcStorageSize(hvalue)]; + Encoder.encodeHandleValue(rawValues[i], 0, hvalue); + } + + return rawValues; + + } + + private String getRemoteDSpaceURL(String handle) throws HandleException + { + if (log.isInfoEnabled()) + { + log.info("Called getRemoteDSpaceURL("+handle+")."); + } + + InputStreamReader jsonStreamReader = null; + String url = null; + try + { + String prefix = handle.split("/")[0]; + String endpoint = this.prefixes.get(prefix); + if (endpoint == null) + { + if (log.isDebugEnabled()) + { + log.debug("Cannot find endpoint for prefix " + prefix + ", throw HANDLE_DOES_NOT_EXIST."); + } + throw new HandleException(HandleException.HANDLE_DOES_NOT_EXIST); + } + + String jsonurl = endpoint + "/resolve/" + handle; + jsonStreamReader = new InputStreamReader( + new URL(jsonurl).openStream(), "UTF-8"); + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(jsonStreamReader); + + if (jsonElement == null || jsonElement.isJsonNull() + || jsonElement.getAsJsonArray().size() == 0 + || jsonElement.getAsJsonArray().get(0).isJsonNull()) + { + if (log.isDebugEnabled()) + { + log.debug("Throw HandleException: HANDLE_DOES_NOT_EXIST."); + } + throw new HandleException(HandleException.HANDLE_DOES_NOT_EXIST); + } + + url = jsonElement.getAsJsonArray().get(0).getAsString(); + } + catch (Exception e) + { + if (log.isDebugEnabled()) + { + log.debug("Exception in getRawHandleValues", e); + } + + // Stack loss as exception does not support cause + throw new HandleException(HandleException.INTERNAL_ERROR); + } + finally + { + if (jsonStreamReader != null) + { + try + { + jsonStreamReader.close(); + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + } + } + if (log.isDebugEnabled()) + { + log.debug(("getRemoteDspaceURL returns " + url)); + } + return url; + } + + /** + * Return true if we have this handle in storage. + * + * @param theHandle + * byte array representation of handle + * @return True if we have this handle in storage + * @exception HandleException + * If an error occurs while calling the Handle API. + */ + public boolean haveNA(byte[] theHandle) throws HandleException + { + if (log.isInfoEnabled()) + { + log.info("Called haveNA"); + } + /* + * Naming authority Handles are in the form: 0.NA/1721.1234 + * + * 0.NA is basically the naming authority for naming authorities. For + * this simple implementation, we will just check if the requestes + * prefix is one that DSpace returns when we call + * handleresolver/listprefixes. + */ + // Which authority does the request pertain to? Remove the heading "0.NA/". + String received = Util.decodeString(theHandle).substring("0.NA/".length()); + + return this.prefixes.containsKey(received); + } + + /** + * Return all handles in local storage which start with the naming authority + * handle. + * + * @param theNAHandle + * byte array representation of naming authority handle + * @return All handles in local storage which start with the naming + * authority handle. + * @exception HandleException + * If an error occurs while calling the Handle API. + */ + public Enumeration getHandlesForNA(byte[] theNAHandle) + throws HandleException + { + String naHandle = Util.decodeString(theNAHandle); + + if (log.isInfoEnabled()) + { + log.info("Called getHandlesForNA for NA " + naHandle); + } + + List<String> handles = getRemoteDSpaceHandles(naHandle); + List<byte[]> results = new LinkedList<byte[]>(); + + for (String handle : handles) + { + // Transforms to byte array + results.add(Util.encodeString(handle)); + } + + return Collections.enumeration(results); + + } + + private List<String> getRemoteDSpaceHandles(String naHandle) + throws HandleException + { + List<String> handles = new ArrayList<String>(); + + String endpoint = this.prefixes.get(naHandle); + if (null == endpoint) + { + // We don't know anything about this prefix, return an empty list. + return handles; + } + + InputStreamReader jsonStreamReader = null; + try + { + String jsonurl = endpoint + "/listhandles/" + naHandle; + jsonStreamReader = new InputStreamReader( + new URL(jsonurl).openStream(), "UTF-8"); + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(jsonStreamReader); + + if (jsonElement != null && jsonElement.getAsJsonArray().size() != 0) + { + for (int i = 0; i < jsonElement.getAsJsonArray().size(); i++) + { + handles.add(jsonElement.getAsJsonArray().get(i) + .getAsString()); + } + } + } + catch (Exception e) + { + if (log.isDebugEnabled()) + { + log.debug("Exception in getHandlesForNA", e); + } + + // Stack loss as exception does not support cause + throw new HandleException(HandleException.INTERNAL_ERROR); + } + finally + { + if (jsonStreamReader != null) + { + try + { + jsonStreamReader.close(); + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + } + } + return handles; + } + + private Properties loadProperties(String filename) throws IOException + { + InputStream is = findConfigFile(filename); + Properties props = new Properties(); + + InputStreamReader ir = null; + // load the configuration + try { + ir = new InputStreamReader(is, "UTF-8"); + props.load(ir); + } catch (UnsupportedEncodingException ex) { + if (log.isInfoEnabled()) + { + log.info("Caught an UnsupportedEncodingException while loading configuration: " + ex.getMessage()); + } + throw new RuntimeException(ex); + } + catch (IOException ex) + { + if (log.isInfoEnabled()) + { + log.info("Caught an IOException while loading configuration: " + ex.getMessage()); + } + throw ex; + } + finally + { + if (ir != null) + { + try + { + ir.close(); + } + catch (IOException ex) + { + // nothing to do. + } + } + if (is != null) + { + try + { + is.close(); + } + catch (IOException ex) + { + // nothing to do. + } + } + } + + return props; + } + + private InputStream findConfigFile(String filename) + { + InputStream is = null; + + // try to load config file as defined in system property: + try + { + String configProperty = System.getProperty("dspace.handle.plugin.configuration"); + if (null != configProperty) + { + is = new FileInputStream(configProperty); + } + } + catch (SecurityException se) + { + // A security manager may stop us from accessing the system properties. + // This isn't really a fatal error though, so catch and ignore + log.warn("Unable to access system properties, ignoring.", se); + } + catch (FileNotFoundException fne) + { + log.warn("Unable to find config file as defined by system property: " + + fne.getMessage()); + } + + if (null == is) + { + // try some default locations + URL url = MultiRemoteDSpaceRepositoryHandlePlugin.class.getResource( + "/" + filename); + if (null == url) + { + if (log.isInfoEnabled()) + { + log.info("Cannot find configuration by using getResource()."); + } + } else { + try + { + is = new FileInputStream(url.getPath()); + log.warn("Falling back to default locations, " + + "found configuration at: " + url.getPath()); + } + catch (FileNotFoundException e) + { + if (log.isInfoEnabled()) + { + // didn't found fallback config, nothing to do about it. + log.info("Unable to open fallback configuration: " + e.getMessage()); + } + } + } + } + + if (null == is) + { + // try to find configuration in the current working directory + // where the user started the handle server. + try + { + is = new FileInputStream("./" + filename); + if (log.isInfoEnabled()) + { + log.info("Loaded configuration from your current working " + + "directory where you started the handle server."); + } + } + catch (FileNotFoundException ex) + { + if (log.isInfoEnabled()) + { + log.info("Can't load config file: " + ex.getMessage()); + } + } + } + + if (is == null) + { + throw new IllegalStateException("Cannot find configuration."); + } + + return is; + } + + private void loadPrefixes(String endpoint) + { + URL url = null; + try { + url = new URL(endpoint + "/listprefixes"); + } catch (MalformedURLException ex) { + log.error(endpoint + "is not a correct URL, will ignore this " + + "DSpace instance.", ex); + } + + String[] prefixes; + try { + InputStreamReader jsonStreamReader = new InputStreamReader(url.openStream(), "UTF-8"); + JsonParser parser = new JsonParser(); + JsonElement jsonElement = parser.parse(jsonStreamReader); + + if (jsonElement != null && jsonElement.getAsJsonArray().size() != 0) + { + for (int i = 0; i < jsonElement.getAsJsonArray().size(); i++) + { + String prefix = jsonElement.getAsJsonArray().get(i).getAsString(); + this.prefixes.put(prefix, endpoint); + + if (log.isInfoEnabled()) + { + log.info("Mapping " + prefix + " to instance at " + endpoint); + } + } + } else { + log.warn("DSpace instance running at " + url + " returns empty prefix list."); + } + } + catch (Exception ex) + { + log.warn("Error while loading prefixes from " + endpoint + ", ignoring.", ex); + } + } + + public static void main(String[] args) throws Exception + { + MultiRemoteDSpaceRepositoryHandlePlugin multi = new MultiRemoteDSpaceRepositoryHandlePlugin(); + try + { + System.out.println(StringUtils.join( + multi.getRemoteDSpaceHandles("123456789"), ",")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + try + { + System.out.println(StringUtils.join( + multi.getRemoteDSpaceHandles("123456780"), ",")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + try + { + System.out.println(multi.getRemoteDSpaceURL("123456789/1")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + try + { + System.out.println(multi.getRemoteDSpaceURL("123456789/1111111")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + try + { + System.out.println(multi.getRemoteDSpaceURL("123456780/1")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + try + { + System.out.println(multi.getRemoteDSpaceURL("123456780/1111111")); + } + catch (HandleException e) + { + e.printStackTrace(); + } + } +} 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/DOI.java b/dspace-api/src/main/java/org/dspace/identifier/DOI.java new file mode 100644 index 0000000000000000000000000000000000000000..893a934ddce5bc65805268297817c20d819bc806 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/DOI.java @@ -0,0 +1,104 @@ +/** + * 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.identifier; + +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.dspace.identifier.doi.DOIIdentifierException; + +/** + * DOI identifiers. + * + * @author Pascal-Nicolas Becker + */ +public class DOI + implements Identifier +{ + public static final String SCHEME = "doi:"; + + public static final String RESOLVER = "http://dx.doi.org"; + + + /** + * This method helps to convert a DOI into a URL. It takes DOIs in one of + * the following formats and returns it as URL (f.e. + * http://dx.doi.org/10.123/456). Allowed formats are: + * <ul> + * <li>doi:10.123/456</li> + * <li>10.123/456</li> + * <li>http://dx.doi.org/10.123/456</li> + * </ul> + * + * @param identifier A DOI that should be returned in external form. + * @return A String containing a URL to the official DOI resolver. + * @throws IllegalArgumentException If identifier is null or an empty String. + * @throws IdentifierException If identifier could not be recognized as valid DOI. + */ + public static String DOIToExternalForm(String identifier) + throws IdentifierException + { + if (null == identifier) + throw new IllegalArgumentException("Identifier is null.", new NullPointerException()); + if (identifier.isEmpty()) + throw new IllegalArgumentException("Cannot format an empty identifier."); + if (identifier.startsWith(SCHEME)) + return RESOLVER + "/" + identifier.substring(SCHEME.length()); + if (identifier.startsWith("10.") && identifier.contains("/")) + return RESOLVER + "/" + identifier; + if (identifier.startsWith(RESOLVER + "/10.")) + return identifier; + + throw new IdentifierException(identifier + "does not seem to be a DOI."); + } + + public static String DOIFromExternalFormat(String identifier) + throws DOIIdentifierException + { + Pattern pattern = Pattern.compile("^" + RESOLVER + "/+(10\\..*)$"); + Matcher matcher = pattern.matcher(identifier); + if (matcher.find()) + { + return SCHEME + matcher.group(1); + } + + throw new DOIIdentifierException("Cannot recognize DOI!", + DOIIdentifierException.UNRECOGNIZED); + } + + /** + * Recognize format of DOI and return it with leading doi-Scheme. + * @param identifier Identifier to format, following format are accepted: + * f.e. 10.123/456, doi:10.123/456, http://dx.doi.org/10.123/456. + * @return Given Identifier with DOI-Scheme, f.e. doi:10.123/456. + * @throws IllegalArgumentException If identifier is empty or null. + * @throws DOIIdentifierException If DOI could not be recognized. + */ + public static String formatIdentifier(String identifier) + throws DOIIdentifierException + { + if (null == identifier) { + throw new IllegalArgumentException("Identifier is null.", new NullPointerException()); + } + if (identifier.startsWith(DOI.SCHEME)) { + return identifier; + } + if (identifier.isEmpty()) { + throw new IllegalArgumentException("Cannot format an empty identifier."); + } + if (identifier.startsWith("10.") && identifier.contains("/")) { + return DOI.SCHEME + identifier; + } + if (identifier.startsWith(RESOLVER + "/10.")) { + return DOI.SCHEME + identifier.substring(18); + } + throw new DOIIdentifierException(identifier + "does not seem to be a DOI.", + DOIIdentifierException.UNRECOGNIZED); + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..b0669c89dd7a6fd5ef45ea3b3a619e80a8511c96 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/DOIIdentifierProvider.java @@ -0,0 +1,936 @@ +/** + * 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.identifier; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.FormatIdentifier; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.identifier.doi.DOIConnector; +import org.dspace.identifier.doi.DOIIdentifierException; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Required; + +/** + * Provide service for DOIs using DataCite. + * + * <p>This class handles reservation, registration and deletion of DOIs using + * the direct API from {@link <a href="http://www.datacite.org">DataCite</a>}. + * Please pay attention that some members of DataCite offer special services + * and want their customers to use special APIs. If you are unsure ask your + * registration agency.</p> + * + * <p>Any identifier a method of this class returns is a string in the following format: doi:10.123/456.</p> + * + * @author Pascal-Nicolas Becker + */ +public class DOIIdentifierProvider + extends IdentifierProvider +{ + private static final Logger log = LoggerFactory.getLogger(DOIIdentifierProvider.class); + + /** + * A DOIConnector connects the DOIIdentifierProvider to the API of the DOI + * registration agency needed to register DOIs. To register DOIs we have to + * care about two APIs: the <link>IdentifierProvider</link> API of DSpace + * and the API of the DOI registration agency. The DOIIdentifierProvider + * manages the DOI database table, generates new DOIs, stores them as + * metadata in DSpace items and so on. To register DOIs at DOI registration + * agencies it uses a DOIConnector. A DOI connector has to register and + * reserve DOIs using the API of the DOI registration agency. If requested + * by the registration agency it has to convert and send metadata of the + * DSpace items. + */ + private DOIConnector connector; + + static final String CFG_PREFIX = "identifier.doi.prefix"; + static final String CFG_NAMESPACE_SEPARATOR = "identifier.doi.namespaceseparator"; + + // Metadata field name elements + // TODO: move these to MetadataSchema or some such? + public static final String MD_SCHEMA = "dc"; + public static final String DOI_ELEMENT = "identifier"; + public static final String DOI_QUALIFIER = "uri"; + + public static final Integer TO_BE_REGISTERED = 1; + public static final Integer TO_BE_RESERVERED = 2; + public static final Integer IS_REGISTERED = 3; + public static final Integer IS_RESERVED = 4; + public static final Integer UPDATE_RESERVERED = 5; + public static final Integer UPDATE_REGISTERED = 6; + public static final Integer UPDATE_BEFORE_REGISTERATION = 7; + public static final Integer TO_BE_DELETED = 8; + public static final Integer DELETED = 9; + + /** + * Prefix of DOI namespace. Set in dspace.cfg. + */ + private String PREFIX; + + /** + * Part of DOI to separate several applications that generate DOIs. + * E.g. it could be 'dspace/' if DOIs generated by DSpace should have the form + * prefix/dspace/uniqueString. Set it to the empty String if DSpace must + * generate DOIs directly after the DOI Prefix. Set in dspace.cfg. + */ + private String NAMESPACE_SEPARATOR; + + protected String getPrefix() + { + if (null == this.PREFIX) + { + this.PREFIX = this.configurationService.getProperty(CFG_PREFIX); + if (null == this.PREFIX) + { + log.warn("Cannot find DOI prefix in configuration!"); + throw new RuntimeException("Unable to load DOI prefix from " + + "configuration. Cannot find property " + + CFG_PREFIX + "."); + } + } + return this.PREFIX; + } + + protected String getNamespaceSeparator() + { + if (null == this.NAMESPACE_SEPARATOR) + { + this.NAMESPACE_SEPARATOR = this.configurationService.getProperty(CFG_NAMESPACE_SEPARATOR); + if (null == this.NAMESPACE_SEPARATOR) + { + this.NAMESPACE_SEPARATOR = ""; + } + } + return this.NAMESPACE_SEPARATOR; + } + + @Required + public void setDOIConnector(DOIConnector connector) + { + this.connector = connector; + } + + /** + * This identifier provider supports identifiers of type + * {@link org.dspace.identifier.DOI}. + * @param identifier to check if it will be supported by this provider. + * @return + */ + @Override + public boolean supports(Class<? extends Identifier> identifier) + { + return DOI.class.isAssignableFrom(identifier); + } + + /** + * This identifier provider supports identifiers in the following format: + * <ul> + * <li>doi:10.123/456</li> + * <li>10.123/456</li> + * <li>http://dx.doi.org/10.123/456</li> + * </ul> + * @param identifier to check if it is in a supported format. + * @return + */ + @Override + public boolean supports(String identifier) + { + try { + DOI.formatIdentifier(identifier); + } catch (IdentifierException e) { + return false; + } catch (IllegalArgumentException e) + { + return false; + } + return true; + } + + + @Override + public String register(Context context, DSpaceObject dso) + throws IdentifierException + { + String doi = mint(context, dso); + // register tries to reserve doi if it's not already. + // So we don't have to reserve it here. + this.register(context, dso, doi); + return doi; + } + + @Override + public void register(Context context, DSpaceObject dso, String identifier) + throws IdentifierException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + // search DOI in our db + try + { + doiRow = loadOrCreateDOI(context, dso, doi); + } catch (SQLException ex) { + log.error("Error in databse connection: " + ex.getMessage()); + throw new RuntimeException("Error in database conncetion.", ex); + } + + if (DELETED == doiRow.getIntColumn("status") || + TO_BE_DELETED == doiRow.getIntColumn("status")) + { + throw new DOIIdentifierException("You tried to register a DOI that " + + "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED); + } + + // Check status of DOI + if (IS_REGISTERED == doiRow.getIntColumn("status")) + { + return; + } + + // change status of DOI + doiRow.setColumn("status", TO_BE_REGISTERED); + try { + DatabaseManager.update(context, doiRow); + context.commit(); + } + catch (SQLException sqle) + { + log.warn("SQLException while changing status of DOI {} to be registered.", doi); + throw new RuntimeException(sqle); + } + } + + /** + * @param context + * @param dso DSpaceObject the DOI should be reserved for. Some metadata of + * this object will be send to the registration agency. + * @param identifier DOI to register in a format that + * {@link FormatIdentifier(String)} accepts. + * @throws IdentifierException If the format of {@code identifier} was + * unrecognized or if it was impossible to + * reserve the DOI (registration agency denied + * for some reason, see logs). + * @throws IllegalArgumentException If {@code identifier} is a DOI already + * registered for another DSpaceObject then + * {@code dso}. + * @see IdentifierProvider.reserve(Context, DSpaceObject, String) + */ + @Override + public void reserve(Context context, DSpaceObject dso, String identifier) + throws IdentifierException, IllegalArgumentException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + try { + // if the doi is in our db already loadOrCreateDOI just returns. + // if it is not loadOrCreateDOI safes the doi. + doiRow = loadOrCreateDOI(context, dso, doi); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + + if (!doiRow.isColumnNull("status")) { + return; + } + + doiRow.setColumn("status", TO_BE_RESERVERED); + try + { + DatabaseManager.update(context, doiRow); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + } + + public void reserveOnline(Context context, DSpaceObject dso, String identifier) + throws IdentifierException, IllegalArgumentException, SQLException + { + String doi = DOI.formatIdentifier(identifier); + // get TableRow and ensure DOI belongs to dso regarding our db + TableRow doiRow = loadOrCreateDOI(context, dso, doi); + + if (DELETED == doiRow.getIntColumn("status") || + TO_BE_DELETED == doiRow.getIntColumn("status")) + { + throw new DOIIdentifierException("You tried to reserve a DOI that " + + "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED); + } + + connector.reserveDOI(context, dso, doi); + + doiRow.setColumn("status", IS_RESERVED); + DatabaseManager.update(context, doiRow); + } + + public void registerOnline(Context context, DSpaceObject dso, String identifier) + throws IdentifierException, IllegalArgumentException, SQLException + { + String doi = DOI.formatIdentifier(identifier); + // get TableRow and ensure DOI belongs to dso regarding our db + TableRow doiRow = loadOrCreateDOI(context, dso, doi); + + if (DELETED == doiRow.getIntColumn("status") || + TO_BE_DELETED == doiRow.getIntColumn("status")) + { + throw new DOIIdentifierException("You tried to register a DOI that " + + "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED); + } + + // register DOI Online + try { + connector.registerDOI(context, dso, doi); + } + catch (DOIIdentifierException die) + { + // do we have to reserve DOI before we can register it? + if (die.getCode() == DOIIdentifierException.RESERVE_FIRST) + { + this.reserveOnline(context, dso, identifier); + connector.registerDOI(context, dso, doi); + } + else + { + throw die; + } + } + + // safe DOI as metadata of the item + try { + saveDOIToObject(context, dso, doi); + } + catch (AuthorizeException ae) + { + throw new IdentifierException("Not authorized to save a DOI as metadata of an dso!", ae); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + + doiRow.setColumn("status", IS_REGISTERED); + DatabaseManager.update(context, doiRow); + } + + public void updateMetadata(Context context, DSpaceObject dso, String identifier) + throws IdentifierException, IllegalArgumentException, SQLException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + doiRow = loadOrCreateDOI(context, dso, doi); + + if (DELETED == doiRow.getIntColumn("status") || + TO_BE_DELETED == doiRow.getIntColumn("status")) + { + throw new DOIIdentifierException("You tried to register a DOI that " + + "is marked as DELETED.", DOIIdentifierException.DOI_IS_DELETED); + } + + if (IS_REGISTERED == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", UPDATE_REGISTERED); + } + else if (TO_BE_REGISTERED == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", UPDATE_BEFORE_REGISTERATION); + } + else if (IS_RESERVED == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", UPDATE_RESERVERED); + } + else + { + return; + } + + DatabaseManager.update(context, doiRow); + } + + public void updateMetadataOnline(Context context, DSpaceObject dso, String identifier) + throws IdentifierException, SQLException + { + String doi = DOI.formatIdentifier(identifier); + + // ensure DOI belongs to dso regarding our db + TableRow doiRow = null; + try + { + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi.substring(DOI.SCHEME.length())); + } + catch (SQLException sqle) + { + log.warn("SQLException while searching a DOI in our db.", sqle); + throw new RuntimeException("Unable to retrieve information about "+ + "a DOI out of database.", sqle); + } + if (null == doiRow) + { + log.error("Cannot update metadata for DOI {}: unable to find it in " + + "our db.", doi); + throw new DOIIdentifierException("Unable to find DOI.", + DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + if (doiRow.getIntColumn("resource_id") != dso.getID() || + doiRow.getIntColumn("resource_type_id") != dso.getType()) + { + log.error("Refuse to update metadata of DOI {} with the metadata of " + + " an object ({}/{}) the DOI is not dedicated to.", + new String[] {doi, dso.getTypeText(), Integer.toString(dso.getID())}); + throw new DOIIdentifierException("Cannot update DOI metadata: " + + "DOI and DSpaceObject does not match!", + DOIIdentifierException.MISMATCH); + } + + if (DELETED == doiRow.getIntColumn("status") || + TO_BE_DELETED == doiRow.getIntColumn("status")) + { + throw new DOIIdentifierException("You tried to update the metadata" + + "of a DOI that is marked as DELETED.", + DOIIdentifierException.DOI_IS_DELETED); + } + + connector.updateMetadata(context, dso, doi); + + if (UPDATE_REGISTERED == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", IS_REGISTERED); + } + else if (UPDATE_BEFORE_REGISTERATION == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", TO_BE_REGISTERED); + } + else if (UPDATE_RESERVERED == doiRow.getIntColumn("status")) + { + doiRow.setColumn("status", IS_RESERVED); + } + + DatabaseManager.update(context, doiRow); + } + + @Override + public String mint(Context context, DSpaceObject dso) + throws IdentifierException + { + String doi = null; + try + { + doi = getDOIByObject(context, dso); + } + catch (SQLException e) + { + log.error("Error while attemping to retrieve information about a DOI for " + + dso.getTypeText() + " with ID " + dso.getID() + "."); + throw new RuntimeException("Error while attempting to retrieve " + + "information about a DOI for " + dso.getTypeText() + + " with ID " + dso.getID() + ".", e); + } + if (null == doi) + { + try + { + TableRow doiRow = loadOrCreateDOI(context, dso, null); + doi = DOI.SCHEME + doiRow.getStringColumn("doi"); + + } + catch (SQLException e) + { + log.error("Error while creating new DOI for Object of " + + "ResourceType {} with id {}.", dso.getType(), dso.getID()); + throw new RuntimeException("Error while attempting to create a " + + "new DOI for " + dso.getTypeText() + " with ID " + + dso.getID() + ".", e); + } + } + return doi; + } + + @Override + public DSpaceObject resolve(Context context, String identifier, String... attributes) + throws IdentifierNotFoundException, IdentifierNotResolvableException + { + String doi = null; + try { + doi = DOI.formatIdentifier(identifier); + } catch (IdentifierException e) { + throw new IdentifierNotResolvableException(e); + } + try + { + DSpaceObject dso = getObjectByDOI(context, doi); + if (null == dso) + { + throw new IdentifierNotFoundException(); + } + return dso; + } + catch (SQLException sqle) + { + log.error("SQLException while searching a DOI in our db.", sqle); + throw new RuntimeException("Unable to retrieve information about "+ + "a DOI out of database.", sqle); + } + catch (IdentifierException e) + { + throw new IdentifierNotResolvableException(e); + } + } + + @Override + public String lookup(Context context, DSpaceObject dso) + throws IdentifierNotFoundException, IdentifierNotResolvableException + { + String doi = null; + try + { + doi = getDOIByObject(context, dso); + } + catch (SQLException e) + { + throw new RuntimeException("Error retrieving DOI out of database.", e); + } + + if (null == doi) + { + throw new IdentifierNotFoundException("No DOI for DSpaceObject of type " + + dso.getTypeText() + " with ID " + dso.getID() + " found."); + } + + return doi; + } + + @Override + public void delete(Context context, DSpaceObject dso) + throws IdentifierException + { + // delete all DOIs for this Item from our database. + try + { + String doi = getDOIByObject(context, dso); + while (null != doi) + { + this.delete(context, dso, doi); + doi = getDOIByObject(context, dso); + } + } + catch (SQLException ex) + { + log.error("Error while attemping to retrieve information about a DOI for " + + dso.getTypeText() + " with ID " + dso.getID() + ".", ex); + throw new RuntimeException("Error while attempting to retrieve " + + "information about a DOI for " + dso.getTypeText() + + " with ID " + dso.getID() + ".", ex); + } + + // delete all DOIs of this item out of its metadata + try { + String doi = getDOIOutOfObject(dso); + + while (null != doi) + { + this.removeDOIFromObject(context, dso, doi); + doi = getDOIOutOfObject(dso); + } + } + catch (AuthorizeException ex) + { + log.error("Error while removing a DOI out of the metadata of an " + + dso.getTypeText() + " with ID " + dso.getID() + ".", ex); + throw new RuntimeException("Error while removing a DOI out of the " + + "metadata of an " + dso.getTypeText() + " with ID " + + dso.getID() + ".", ex); + + } + catch (SQLException ex) + { + log.error("Error while removing a DOI out of the metadata of an " + + dso.getTypeText() + " with ID " + dso.getID() + ".", ex); + throw new RuntimeException("Error while removing a DOI out of the " + + "metadata of an " + dso.getTypeText() + " with ID " + + dso.getID() + ".", ex); + } + } + + @Override + public void delete(Context context, DSpaceObject dso, String identifier) + throws IdentifierException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + try + { + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + + // check if DOI belongs to dso + if (null != doiRow) + { + if (doiRow.getIntColumn("resource_id") != dso.getID() || + doiRow.getIntColumn("resource_type_id") != dso.getType()) + { + throw new DOIIdentifierException("Trying to delete a DOI out of " + + "an object that is not addressed by the DOI.", + DOIIdentifierException.MISMATCH); + } + } + + // remove DOI from metadata + try + { + removeDOIFromObject(context, dso, doi); + } + catch (AuthorizeException ex) + { + log.error("Not authorized to delete a DOI out of an Item.", ex); + throw new DOIIdentifierException("Not authorized to delete DOI.", + ex, DOIIdentifierException.UNAUTHORIZED_METADATA_MANIPULATION); + } + catch (SQLException ex) + { + log.error("SQLException occured while deleting a DOI out of an item: " + + ex.getMessage()); + throw new RuntimeException("Error while deleting a DOI out of the " + + "metadata of an Item " + dso.getID(), ex); + } + + // change doi status in db if necessary. + if (null != doiRow) + { + if(doiRow.isColumnNull("status")) + { + doiRow.setColumn("status", DELETED); + } + else + { + doiRow.setColumn("status", TO_BE_DELETED); + } + try { + DatabaseManager.update(context, doiRow); + context.commit(); + } + catch (SQLException sqle) + { + log.warn("SQLException while changing status of DOI {} to be deleted.", doi); + throw new RuntimeException(sqle); + } + } + + // DOI is a permanent identifier. DataCite for example does not delete + // DOIS. But it is possible to mark a DOI as "inactive". + } + + public void deleteOnline(Context context, String identifier) + throws DOIIdentifierException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = null; + + try + { + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + } + catch (SQLException sqle) + { + throw new RuntimeException(sqle); + } + if(null == doiRow) + { + throw new DOIIdentifierException("This identifier: " + identifier + + " isn't in our database", + DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + if (TO_BE_DELETED != doiRow.getIntColumn("status")) + { + log.error("This identifier: {} couldn't be deleted. " + + "Delete it first from metadata.", + DOI.SCHEME + doiRow.getStringColumn("doi")); + throw new IllegalArgumentException("Couldn't delete this identifier:" + + DOI.SCHEME + doiRow.getStringColumn("doi") + + ". Delete it first from metadata."); + } + connector.deleteDOI(context, doi); + + doiRow.setColumn("status", DELETED); + try { + DatabaseManager.update(context, doiRow); + context.commit(); + } + catch (SQLException sqle) + { + log.warn("SQLException while changing status of DOI {} deleted.", doi); + throw new RuntimeException(sqle); + } + } + + /** + * Returns a DSpaceObject depending on its DOI. + * @param context the context + * @param identifier The DOI in a format that is accepted by + * {@link formatIdentifier(String)}. + * @return Null if the DOI couldn't be found or the associated DSpaceObject. + * @throws SQLException + * @throws IdentifierException If {@code identifier} is null or an empty string. + * @throws IllegalArgumentException If the identifier couldn't be recognized as DOI. + */ + public static DSpaceObject getObjectByDOI(Context context, String identifier) + throws SQLException, DOIIdentifierException, IllegalArgumentException + { + String doi = DOI.formatIdentifier(identifier); + TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + + if (null == doiRow) + { + return null; + } + + if (doiRow.isColumnNull("resource_type_id") || + doiRow.isColumnNull("resource_id")) + { + log.error("Found DOI " + doi + + " in database, but no assigned Object could be found."); + throw new IllegalStateException("Found DOI " + doi + + " in database, but no assigned Object could be found."); + } + + return DSpaceObject.find(context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + } + + /** + * Search the database for a DOI, using the type and id of an DSpaceObject. + * + * @param context + * @param dso DSpaceObject to find doi for. DOIs with status TO_BE_DELETED will be + * ignored. + * @return The DOI as String or null if DOI was not found. + * @throws SQLException + */ + public static String getDOIByObject(Context context, DSpaceObject dso) + throws SQLException + { + String sql = "SELECT * FROM Doi WHERE resource_type_id = ? " + + "AND resource_id = ? AND ((status != ? AND status != ?) OR status IS NULL)"; + + TableRow doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, + dso.getType(), dso.getID(), DOIIdentifierProvider.TO_BE_DELETED, + DOIIdentifierProvider.DELETED); + if (null == doiRow) + { + return null; + } + + if (doiRow.isColumnNull("doi")) + { + log.error("A DOI with an empty doi column was found in the database. DSO-Type: " + + dso.getTypeText() + ", ID: " + dso.getID() + "."); + throw new IllegalStateException("A DOI with an empty doi column " + + "was found in the database. DSO-Type: " + dso.getTypeText() + + ", ID: " + dso.getID() + "."); + } + + return DOI.SCHEME + doiRow.getStringColumn("doi"); + } + + /** + * Load a DOI from the database or creates it if it does not exist. This + * method can be used to ensure that a DOI exists in the database and to + * load the appropriate TableRow. As protected method we don't check if the + * DOI is in a decent format, use DOI.formatIdentifier(String) if necessary. + * + * @param context + * @param dso The DSpaceObject the DOI should be loaded or created for. + * @param doi A DOI or null if a DOI should be generated. The generated DOI + * can be found in the appropriate column for the TableRow. + * @return The database row of the object. + * @throws SQLException In case of an error using the database. + * @throws DOIIdentifierException If {@code doi} is not part of our prefix or + * DOI is registered for another object already. + */ + protected TableRow loadOrCreateDOI(Context context, DSpaceObject dso, String doi) + throws SQLException, DOIIdentifierException + { + TableRow doiRow = null; + if (null != doi) + { + // we expect DOIs to have the DOI-Scheme except inside the doi table: + doi = doi.substring(DOI.SCHEME.length()); + + // check if DOI is already in Database + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", doi); + if (null != doiRow) + { + // check if DOI already belongs to dso + if (doiRow.getIntColumn("resource_id") == dso.getID() && + doiRow.getIntColumn("resource_type_id") == dso.getType()) + { + return doiRow; + } + else + { + throw new DOIIdentifierException("Trying to create a DOI " + + "that is already reserved for another object.", + DOIIdentifierException.DOI_ALREADY_EXISTS); + } + } + + // check prefix + if (!doi.startsWith(this.getPrefix() + "/")) + { + throw new DOIIdentifierException("Trying to create a DOI " + + "that's not part of our Namespace!", + DOIIdentifierException.FOREIGN_DOI); + } + // prepare new doiRow + doiRow = DatabaseManager.create(context, "Doi"); + } + else + { + // We need to generate a new DOI. + doiRow = DatabaseManager.create(context, "Doi"); + + doi = this.getPrefix() + "/" + this.getNamespaceSeparator() + + doiRow.getIntColumn("doi_id"); + } + + doiRow.setColumn("doi", doi); + doiRow.setColumn("resource_type_id", dso.getType()); + doiRow.setColumn("resource_id", dso.getID()); + doiRow.setColumnNull("status"); + if (0 == DatabaseManager.update(context, doiRow)) + { + throw new RuntimeException("Cannot save DOI to databse for unkown reason."); + } + + return doiRow; + } + + /** + * Loads a DOI out of the metadata of an DSpaceObject. + * @param dso + * @return The DOI or null if no DOI was found. + */ + public static String getDOIOutOfObject(DSpaceObject dso) + throws DOIIdentifierException { + // FIXME + if (!(dso instanceof Item)) + { + throw new IllegalArgumentException("We currently support DOIs for " + + "Items only, not for " + dso.getTypeText() + "."); + } + Item item = (Item)dso; + + DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + for (DCValue id : metadata) + { + if (id.value.startsWith(DOI.RESOLVER + "/10.")) + { + return DOI.DOIFromExternalFormat(id.value); + } + } + return null; + } + + /** + * Adds a DOI to the metadata of an item. + * + * @param context + * @param dso DSpaceObject the DOI should be added to. + * @param doi The DOI that should be added as metadata. + * @throws SQLException + * @throws AuthorizeException + */ + protected void saveDOIToObject(Context context, DSpaceObject dso, String doi) + throws SQLException, AuthorizeException, IdentifierException + { + // FIXME + if (!(dso instanceof Item)) + { + throw new IllegalArgumentException("We currently support DOIs for " + + "Items only, not for " + dso.getTypeText() + "."); + } + Item item = (Item) dso; + + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, DOI.DOIToExternalForm(doi)); + try + { + item.update(); + context.commit(); + } catch (SQLException ex) { + throw ex; + } catch (AuthorizeException ex) { + throw ex; + } + } + + /** + * Removes a DOI out of the metadata of a DSpaceObject. + * + * @param context + * @param dso The DSpaceObject the DOI should be removed from. + * @param doi The DOI to remove out of the metadata. + * @throws AuthorizeException + * @throws SQLException + */ + protected void removeDOIFromObject(Context context, DSpaceObject dso, String doi) + throws AuthorizeException, SQLException, IdentifierException + { + // FIXME + if (!(dso instanceof Item)) + { + throw new IllegalArgumentException("We currently support DOIs for " + + "Items only, not for " + dso.getTypeText() + "."); + } + Item item = (Item)dso; + + DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + List<String> remainder = new ArrayList<String>(); + + for (DCValue id : metadata) + { + if (!id.value.equals(DOI.DOIToExternalForm(doi))) + { + remainder.add(id.value); + } + } + + item.clearMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, + remainder.toArray(new String[remainder.size()])); + try { + item.update(); + context.commit(); + } catch (SQLException e) { + throw e; + } catch (AuthorizeException e) { + throw e; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/EZIDIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/EZIDIdentifierProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..50f4cc74a65458be79be102a81328631ecf8f58d --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/EZIDIdentifierProvider.java @@ -0,0 +1,702 @@ +/** + * 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.identifier; + +import java.io.IOException; +import java.net.*; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.ItemIterator; +import org.dspace.core.Context; +import org.dspace.identifier.ezid.EZIDRequest; +import org.dspace.identifier.ezid.EZIDRequestFactory; +import org.dspace.identifier.ezid.EZIDResponse; +import org.dspace.identifier.ezid.Transform; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Required; + +/** + * Provide service for DOIs through DataCite using the EZID service. + * + * <p>Configuration of this class is is in two parts.</p> + * + * <p>Installation-specific configuration (credentials and the "shoulder" value + * which forms a prefix of the site's DOIs) is supplied from property files in + * [DSpace]/config**.</p> + * + * <dl> + * <dt>identifier.doi.ezid.shoulder</dt> + * <dd>base of the site's DOIs. Example: 10.5072/FK2</dd> + * <dt>identifier.doi.ezid.user</dt> + * <dd>EZID username.</dd> + * <dt>identifier.doi.ezid.password</dt> + * <dd>EZID password.</dd> + * <dt>identifier.doi.ezid.publisher</dt> + * <dd>A default publisher, for Items not previously published. EZID requires a publisher.</dd> + * </dl> + * + * <p>Then there are properties injected using Spring:</p> + * <ul> + * <li>There is a Map (with the property name "crosswalk") from EZID + * metadata field names into DSpace field names, injected by Spring. Specify + * the fully-qualified names of all metadata fields to be looked up on a DSpace + * object and their values set on mapped fully-qualified names in the object's + * DataCite metadata.</li> + * + * <li>A second map ("crosswalkTransform") provides Transform instances + * mapped from EZID metadata field names. This allows the crosswalk to rewrite + * field values where the form maintained by DSpace is not directly usable in + * EZID metadata.</li> + * </ul> + * + * @author mwood + */ +public class EZIDIdentifierProvider + extends IdentifierProvider +{ + private static final Logger log = LoggerFactory.getLogger(EZIDIdentifierProvider.class); + + // Configuration property names + static final String CFG_SHOULDER = "identifier.doi.ezid.shoulder"; + static final String CFG_USER = "identifier.doi.ezid.user"; + static final String CFG_PASSWORD = "identifier.doi.ezid.password"; + static final String CFG_PUBLISHER = "identifier.doi.ezid.publisher"; + + // DataCite metadata field names + static final String DATACITE_PUBLISHER = "datacite.publisher"; + static final String DATACITE_PUBLICATION_YEAR = "datacite.publicationyear"; + + // DSpace metadata field name elements + // XXX move these to MetadataSchema or some such + public static final String MD_SCHEMA = "dc"; + public static final String DOI_ELEMENT = "identifier"; + public static final String DOI_QUALIFIER = null; + + private static final String DOI_SCHEME = "doi:"; + + /** Map DataCite metadata into local metadata. */ + private static Map<String, String> crosswalk = new HashMap<String, String>(); + + /** Converters to be applied to specific fields. */ + private static Map<String, Transform> transforms = new HashMap<String, Transform>(); + + /** Factory for EZID requests. */ + private static EZIDRequestFactory requestFactory; + + @Override + public boolean supports(Class<? extends Identifier> identifier) + { + return DOI.class.isAssignableFrom(identifier); + } + + @Override + public boolean supports(String identifier) + { + if (null == identifier) + { + return false; + } + else + { + return identifier.startsWith(DOI_SCHEME); + } // XXX more thorough test? + } + + @Override + public String register(Context context, DSpaceObject dso) + throws IdentifierException + { + log.debug("register {}", dso); + + if (!(dso instanceof Item)) + { + throw new IdentifierException("Unsupported object type " + dso.getTypeText()); + } + + Item item = (Item)dso; + DCValue[] identifiers = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + for (DCValue identifier : identifiers) + { + if ((null != identifier.value) && (identifier.value.startsWith(DOI_SCHEME))) + { + return identifier.value; + } + } + + String id = mint(context, item); + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, id); + try { + item.update(); + context.commit(); + } catch (SQLException ex) { + throw new IdentifierException("New identifier not stored", ex); + } catch (AuthorizeException ex) { + throw new IdentifierException("New identifier not stored", ex); + } + log.info("Registered {}", id); + return id; + } + + @Override + public void register(Context context, DSpaceObject object, String identifier) + { + log.debug("register {} as {}", object, identifier); + + if (!(object instanceof Item)) + { + // TODO throw new IdentifierException("Unsupported object type " + object.getTypeText()); + log.error("Unsupported object type " + object.getTypeText()); + return; + } + + EZIDResponse response; + try { + EZIDRequest request = requestFactory.getInstance(loadAuthority(), + loadUser(), loadPassword()); + response = request.create(identifier, crosswalkMetadata(object)); + } catch (IdentifierException e) { + log.error("Identifier '{}' not registered: {}", identifier, e.getMessage()); + return; + } catch (IOException e) { + log.error("Identifier '{}' not registered: {}", identifier, e.getMessage()); + return; + } catch (URISyntaxException e) { + log.error("Identifier '{}' not registered: {}", identifier, e.getMessage()); + return; + } + + if (response.isSuccess()) + { + Item item = (Item)object; + try { + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, + idToDOI(identifier)); + item.update(); + context.commit(); + log.info("registered {}", identifier); + } catch (SQLException ex) { + // TODO throw new IdentifierException("New identifier not stored", ex); + log.error("New identifier not stored", ex); + } catch (AuthorizeException ex) { + // TODO throw new IdentifierException("New identifier not stored", ex); + log.error("New identifier not stored", ex); + } catch (IdentifierException ex) { + log.error("New identifier not stored", ex); + } + } + else + { + log.error("Identifier '{}' not registered -- EZID returned: {}", + identifier, response.getEZIDStatusValue()); + } + } + + @Override + public void reserve(Context context, DSpaceObject dso, String identifier) + throws IdentifierException + { + log.debug("reserve {}", identifier); + + EZIDResponse response; + try { + EZIDRequest request = requestFactory.getInstance(loadAuthority(), + loadUser(), loadPassword()); + Map<String, String> metadata = crosswalkMetadata(dso); + metadata.put("_status", "reserved"); + response = request.create(identifier, metadata); + } catch (IOException e) { + log.error("Identifier '{}' not registered: {}", identifier, e.getMessage()); + return; + } catch (URISyntaxException e) { + log.error("Identifier '{}' not registered: {}", identifier, e.getMessage()); + return; + } + + if (response.isSuccess()) + { + Item item = (Item)dso; + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, idToDOI(identifier)); + try { + item.update(); + context.commit(); + log.info("reserved {}", identifier); + } catch (SQLException ex) { + throw new IdentifierException("New identifier not stored", ex); + } catch (AuthorizeException ex) { + throw new IdentifierException("New identifier not stored", ex); + } + } + else + { + log.error("Identifier '{}' not registered -- EZID returned: {}", + identifier, response.getEZIDStatusValue()); + } + } + + @Override + public String mint(Context context, DSpaceObject dso) + throws IdentifierException + { + log.debug("mint for {}", dso); + + // Compose the request + EZIDRequest request; + try { + request = requestFactory.getInstance(loadAuthority(), loadUser(), loadPassword()); + } catch (URISyntaxException ex) { + log.error(ex.getMessage()); + throw new IdentifierException("DOI request not sent: " + ex.getMessage()); + } + + // Send the request + EZIDResponse response; + try + { + response = request.mint(crosswalkMetadata(dso)); + } catch (IOException ex) { + log.error("Failed to send EZID request: {}", ex.getMessage()); + throw new IdentifierException("DOI request not sent: " + ex.getMessage()); + } catch (URISyntaxException ex) { + log.error("Failed to send EZID request: {}", ex.getMessage()); + throw new IdentifierException("DOI request not sent: " + ex.getMessage()); + } + + // Good response? + if (HttpURLConnection.HTTP_CREATED != response.getHttpStatusCode()) + { + log.error("EZID server responded: {} {}: {}", + new String[] { + String.valueOf(response.getHttpStatusCode()), + response.getHttpReasonPhrase(), + response.getEZIDStatusValue() + }); + throw new IdentifierException("DOI not created: " + + response.getHttpReasonPhrase() + + ": " + + response.getEZIDStatusValue()); + } + + // Extract the DOI from the content blob + if (response.isSuccess()) + { + String value = response.getEZIDStatusValue(); + int end = value.indexOf('|'); // Following pipe is "shadow ARK" + if (end < 0) + { + end = value.length(); + } + String doi = value.substring(0, end).trim(); + log.info("Created {}", doi); + return doi; + } + else + { + log.error("EZID responded: {}", response.getEZIDStatusValue()); + throw new IdentifierException("No DOI returned"); + } + } + + @Override + public DSpaceObject resolve(Context context, String identifier, + String... attributes) + throws IdentifierNotFoundException, IdentifierNotResolvableException + { + log.debug("resolve {}", identifier); + + ItemIterator found; + try { + found = Item.findByMetadataField(context, + MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, + idToDOI(identifier)); + } catch (IdentifierException ex) { + log.error(ex.getMessage()); + throw new IdentifierNotResolvableException(ex); + } catch (SQLException ex) { + log.error(ex.getMessage()); + throw new IdentifierNotResolvableException(ex); + } catch (AuthorizeException ex) { + log.error(ex.getMessage()); + throw new IdentifierNotResolvableException(ex); + } catch (IOException ex) { + log.error(ex.getMessage()); + throw new IdentifierNotResolvableException(ex); + } + try { + if (!found.hasNext()) + { + throw new IdentifierNotFoundException("No object bound to " + identifier); + } + Item found1 = found.next(); + if (found.hasNext()) + { + log.error("More than one object bound to {}!", identifier); + } + log.debug("Resolved to {}", found1); + return found1; + } catch (SQLException ex) { + log.error(ex.getMessage()); + throw new IdentifierNotResolvableException(ex); + } + } + + @Override + public String lookup(Context context, DSpaceObject object) + throws IdentifierNotFoundException, IdentifierNotResolvableException + { + log.debug("lookup {}", object); + + if (!(object instanceof Item)) + { + throw new IllegalArgumentException("Unsupported type " + object.getTypeText()); + } + + Item item = (Item)object; + DCValue found = null; + for (DCValue candidate : item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null)) + { + if (candidate.value.startsWith(DOI_SCHEME)) + { + found = candidate; + break; + } + } + if (null != found) + { + log.debug("Found {}", found.value); + return found.value; + } + else + { + throw new IdentifierNotFoundException(object.getTypeText() + " " + + object.getID() + " has no DOI"); + } + } + + @Override + public void delete(Context context, DSpaceObject dso) + throws IdentifierException + { + log.debug("delete {}", dso); + + if (!(dso instanceof Item)) + { + throw new IllegalArgumentException("Unsupported type " + dso.getTypeText()); + } + + Item item = (Item)dso; + + // delete from EZID + DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + List<String> remainder = new ArrayList<String>(); + int skipped = 0; + for (DCValue id : metadata) + { + if (!id.value.startsWith(DOI_SCHEME)) + { + remainder.add(id.value); + continue; + } + + EZIDResponse response; + try { + EZIDRequest request = requestFactory.getInstance(loadAuthority(), + loadUser(), loadPassword()); + response = request.delete(DOIToId(id.value)); + } catch (URISyntaxException e) { + log.error("Bad URI in metadata value: {}", e.getMessage()); + remainder.add(id.value); + skipped++; + continue; + } catch (IOException e) { + log.error("Failed request to EZID: {}", e.getMessage()); + remainder.add(id.value); + skipped++; + continue; + } + if (!response.isSuccess()) + { + log.error("Unable to delete {} from DataCite: {}", id.value, + response.getEZIDStatusValue()); + remainder.add(id.value); + skipped++; + continue; + } + log.info("Deleted {}", id.value); + } + + // delete from item + item.clearMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, + remainder.toArray(new String[remainder.size()])); + try { + item.update(); + context.commit(); + } catch (SQLException e) { + log.error("Failed to re-add identifiers: {}", e.getMessage()); + } catch (AuthorizeException e) { + log.error("Failed to re-add identifiers: {}", e.getMessage()); + } + + if (skipped > 0) + { + throw new IdentifierException(skipped + " identifiers could not be deleted."); + } + } + + @Override + public void delete(Context context, DSpaceObject dso, String identifier) + throws IdentifierException + { + log.debug("delete {} from {}", identifier, dso); + + if (!(dso instanceof Item)) + { + throw new IllegalArgumentException("Unsupported type " + dso.getTypeText()); + } + + Item item = (Item)dso; + + DCValue[] metadata = item.getMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + List<String> remainder = new ArrayList<String>(); + int skipped = 0; + for (DCValue id : metadata) + { + if (!id.value.equals(idToDOI(identifier))) + { + remainder.add(id.value); + continue; + } + + EZIDResponse response; + try { + EZIDRequest request = requestFactory.getInstance(loadAuthority(), + loadUser(), loadPassword()); + response = request.delete(DOIToId(id.value)); + } catch (URISyntaxException e) { + log.error("Bad URI in metadata value {}: {}", id.value, e.getMessage()); + remainder.add(id.value); + skipped++; + continue; + } catch (IOException e) { + log.error("Failed request to EZID: {}", e.getMessage()); + remainder.add(id.value); + skipped++; + continue; + } + + if (!response.isSuccess()) + { + log.error("Unable to delete {} from DataCite: {}", id.value, + response.getEZIDStatusValue()); + remainder.add(id.value); + skipped++; + continue; + } + log.info("Deleted {}", id.value); + } + + // delete from item + item.clearMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null); + item.addMetadata(MD_SCHEMA, DOI_ELEMENT, DOI_QUALIFIER, null, + remainder.toArray(new String[remainder.size()])); + try { + item.update(); + context.commit(); + } catch (SQLException e) { + log.error("Failed to re-add identifiers: {}", e.getMessage()); + } catch (AuthorizeException e) { + log.error("Failed to re-add identifiers: {}", e.getMessage()); + } + + if (skipped > 0) + { + throw new IdentifierException(identifier + " could not be deleted."); + } + } + + /** + * Format a naked identifier as a DOI with our configured authority prefix. + * + * @throws IdentifierException if authority prefix is not configured. + */ + String idToDOI(String id) + throws IdentifierException + { + return "doi:" + loadAuthority() + id; + } + + /** + * Remove scheme and our configured authority prefix from a doi: URI string. + * @return naked local identifier. + * @throws IdentifierException if authority prefix is not configured. + */ + String DOIToId(String DOI) + throws IdentifierException + { + String prefix = "doi:" + loadAuthority(); + if (DOI.startsWith(prefix)) + { + return DOI.substring(prefix.length()); + } + else + { + return DOI; + } + } + + /** + * Get configured value of EZID username. + * @throws IdentifierException + */ + private String loadUser() + throws IdentifierException + { + String user = configurationService.getProperty(CFG_USER); + if (null != user) + { + return user; + } + else + { + throw new IdentifierException("Unconfigured: define " + CFG_USER); + } + } + + /** + * Get configured value of EZID password. + * @throws IdentifierException + */ + private String loadPassword() + throws IdentifierException + { + String password = configurationService.getProperty(CFG_PASSWORD); + if (null != password) + { + return password; + } + else + { + throw new IdentifierException("Unconfigured: define " + CFG_PASSWORD); + } + } + + /** + * Get configured value of EZID "shoulder". + * @throws IdentifierException + */ + private String loadAuthority() + throws IdentifierException + { + String shoulder = configurationService.getProperty(CFG_SHOULDER); + if (null != shoulder) + { + return shoulder; + } + else + { + throw new IdentifierException("Unconfigured: define " + CFG_SHOULDER); + } + } + + /** + * Map selected DSpace metadata to fields recognized by DataCite. + */ + private Map<String, String> crosswalkMetadata(DSpaceObject dso) + { + if ((null == dso) || !(dso instanceof Item)) + { + throw new IllegalArgumentException("Must be an Item"); + } + Item item = (Item) dso; // TODO generalize to DSO when all DSOs have metadata. + + Map<String, String> mapped = new HashMap<String, String>(); + + for (Entry<String, String> datum : crosswalk.entrySet()) + { + DCValue[] values = item.getMetadata(datum.getValue()); + if (null != values) + { + for (DCValue value : values) + { + String key = datum.getKey(); + String mappedValue; + Transform xfrm = transforms.get(key); + if (null != xfrm) + { + try { + mappedValue = xfrm.transform(value.value); + } catch (Exception ex) { + log.error("Unable to transform '{}' from {} to {}: {}", + new String[] { + value.value, + value.toString(), + key, + ex.getMessage() + }); + continue; + } + } + else + { + mappedValue = value.value; + } + mapped.put(key, mappedValue); + } + } + } + + // Supply a default publisher, if the Item has none. + if (!mapped.containsKey(DATACITE_PUBLISHER)) + { + String publisher = configurationService.getPropertyAsType(CFG_PUBLISHER, "unknown"); + log.info("Supplying default publisher: {}", publisher); + mapped.put(DATACITE_PUBLISHER, publisher); + } + + // Supply current year as year of publication, if the Item has none. + if (!mapped.containsKey(DATACITE_PUBLICATION_YEAR)) + { + String year = String.valueOf(Calendar.getInstance().get(Calendar.YEAR)); + log.info("Supplying default publication year: {}", year); + mapped.put(DATACITE_PUBLICATION_YEAR, year); + } + + // TODO find a way to get a current direct URL to the object and set _target + // mapped.put("_target", url); + + return mapped; + } + + @Required + public void setCrosswalk(Map<String, String> aCrosswalk) + { + crosswalk = aCrosswalk; + } + + public void setCrosswalkTransform(Map<String, Transform> transformMap) + { + transforms = transformMap; + } + + @Required + public static void setRequestFactory(EZIDRequestFactory aRequestFactory) + { + requestFactory = aRequestFactory; + } +} 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/identifier/doi/DOIConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..666d69d8257ba8e4a47d4f7a236b7945c34fcda6 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConnector.java @@ -0,0 +1,103 @@ +/** + * 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.identifier.doi; + +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; + +/** + * A DOIConnector handles all calls to the API of your DOI registry. + * + * A DOIConnector should care about rules of the registration agency. For + * example, if the registration agency wants us to reserve a DOI before we can + * register it, the DOIConnector should check if a DOI is reserved. Use a + * {@link DOIIdenfierException} and set its error code in case of any errors. + * For the given example you should use + * {@code DOIIdentifierException.RESERVER_FIRST} as error code. + * + * @author Pascal-Nicolas Becker + */ +public interface DOIConnector { + public boolean isDOIReserved(Context context, String doi) + throws DOIIdentifierException; + + public boolean isDOIReserved(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException; + + public boolean isDOIRegistered(Context context, String doi) + throws DOIIdentifierException; + + public boolean isDOIRegistered(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException; + + /** + * Sends the DELETE-Request to the DOI registry. + * + * <p>This method sends a request to "delete" a DOI. As DOIs are persistent + * identifiers they should never be deleted. For example, if you send a HTTP + * DELETE request to the DataCite Metadata API directly, it will set the DOI + * to inactive.</p> + * + * @param context + * @param doi + * @return + * @throws DOIIdentifierException + */ + public void deleteDOI(Context context, String doi) + throws DOIIdentifierException; + + /** + * Sends a request to the DOI registry to reserve a DOI. + * + * The DOIConnector should check weather this DOI is reserved for another + * object already. In this case it should throw an {@link + * DOIIdentifierException} and set the error code to {@code + * DOIIdentifierException.DOI_ALREADY_EXISTS}. + * + * @param context + * @param dso + * @param doi + * @return + * @throws DOIIdentifierException + */ + public void reserveDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException; + /** + * Sends a request to the DOI registry to register a DOI. + * + * The DOIConnector ensures compliance with the workflow of the registration + * agency. For example, if a DOI has to be reserved before it can be + * registered the DOIConnector has to check if it is reserved. In this case + * you can throw an DOIIdentifierExcpetion and set the error code to + * {@link DOIIdentifierException.RESERVE_FIRST}. + * + * @param context + * @param dso + * @param doi + * @return + * @throws DOIIdentifierException + */ + public void registerDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException; + + /** + * Sends a request to the DOI registry to update metadata for a DOI. + * + * The DOIConnector should check weather the DOI is reserved or registered + * for the specified DSpace Object before it sends the metadata update. + * + * @param context + * @param dso + * @param doi + * @return + * @throws IdentifierException + */ + public void updateMetadata(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException; +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..65f7c7c7e521b0507dafb092dce9986f78b4903b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIConsumer.java @@ -0,0 +1,108 @@ +/** + * 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.identifier.doi; + +import java.util.HashSet; +import java.util.Set; +import org.apache.log4j.Logger; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.event.Consumer; +import org.dspace.event.Event; +import org.dspace.identifier.DOIIdentifierProvider; +import org.dspace.identifier.IdentifierException; +import org.dspace.identifier.IdentifierNotFoundException; +import org.dspace.search.SearchConsumer; +import org.dspace.utils.DSpace; + +/** + * + * @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de) + */ +public class DOIConsumer implements Consumer +{ + /** log4j logger */ + private static Logger log = Logger.getLogger(DOIConsumer.class); + + @Override + public void initialize() throws Exception { + // nothing to do + // we can ask spring to give as a properly setuped instance of + // DOIIdentifierProvider. Doing so we don't have to configure it and + // can load it in consume method as this is not very expensive. + + } + + // as we use asynchronous metadata update, our updates are not very expensive. + // so we can do everything in the consume method. + @Override + public void consume(Context ctx, Event event) throws Exception { + if (event.getSubjectType() != Constants.ITEM) + { + log.warn("DOIConsumer should not have been given this kind of " + + "subject in an event, skipping: " + event.toString()); + return; + } + if (Event.MODIFY_METADATA != event.getEventType()) + { + log.warn("DOIConsumer should not have been given this kind of " + + "event type, skipping: " + event.toString()); + return; + } + + DSpaceObject dso = event.getSubject(ctx); + //FIXME + if (!(dso instanceof Item)) + { + log.warn("DOIConsumer got an event whose subject was not an item, " + + "skipping: " + event.toString()); + } + Item item = (Item) dso; + + DOIIdentifierProvider provider = new DSpace().getSingletonService( + DOIIdentifierProvider.class); + + String doi = null; + try { + doi = provider.lookup(ctx, dso); + } + catch (IdentifierNotFoundException ex) + { + log.warn("DOIConsumer cannot handles items without DOIs, skipping: " + + event.toString()); + } + try + { + provider.updateMetadata(ctx, dso, doi); + } + catch (IllegalArgumentException ex) + { + // should not happen, as we got the DOI from the DOIProvider + log.warn("DOIConsumer caught an IdentifierException.", ex); + } + catch (IdentifierException ex) + { + log.warn("DOIConsumer cannot update metadata for Item with ID " + + item.getID() + " and DOI " + doi + ".", ex); + } + } + + @Override + public void end(Context ctx) throws Exception { + + + } + + @Override + public void finish(Context ctx) throws Exception { + // nothing to do + } + +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIIdentifierException.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIIdentifierException.java new file mode 100644 index 0000000000000000000000000000000000000000..a5d3be6560752529966d03b2850e236044a3fdb3 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIIdentifierException.java @@ -0,0 +1,175 @@ +/** + * 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.identifier.doi; + +import org.dspace.identifier.IdentifierException; + +/** + * + * @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de) + */ +public class DOIIdentifierException extends IdentifierException { + + /** + * Default. + */ + public static final int CODE_NOT_SET = 0; + /** + * A specified DOI does not exists. + */ + public static final int DOI_DOES_NOT_EXIST = 1; + /** + * A DOI cannot be created, registered, reserved, and so on because it is + * already used for another object. + */ + public static final int DOI_ALREADY_EXISTS = 2; + /** + * A DOI cannot be created, registered, reserved and so on because it uses a + * foreign prefix. + */ + public static final int FOREIGN_DOI = 3; + /** + * We got a answer from a registration agency that could not be parsed. + * Either they changed there API or the DOIConnector does not implement it + * properly. + */ + public static final int BAD_ANSWER = 4; + /** + * The registration agency was unable to parse our request. Either they + * changed there API or the DOIConnector does not implement it properly. + */ + public static final int BAD_REQUEST = 5; + /** + * Some registration agencies request that a DOI gets reserved before it can + * be registered. This error code signals that a unreserved DOI should be + * registered and that the registration agency denied it. + */ + public static final int RESERVE_FIRST = 6; + /** + * Error while authenticating against the registration agency. + */ + public static final int AUTHENTICATION_ERROR = 7; + /** + * A internal error occurred either in the registration agency or in the + * DOIConnector. + */ + public static final int INTERNAL_ERROR = 8; + /** + * An error arose while metadata conversion. + */ + public static final int CONVERSION_ERROR = 9; + /** + * A DOI and a provided object does not match. This error occurs if you try + * to connect an object with a DOI that is reserved or registered for + * another object. + */ + public static final int MISMATCH = 10; + /** + * An identifier supplied as DOI could not be recognized. + */ + public static final int UNRECOGNIZED = 11; + /** + * DSpace did not allowed to manipulate the metadata of an DSpaceObject. + */ + public static final int UNAUTHORIZED_METADATA_MANIPULATION = 12; + /** + * You tried to reserve or register a DOI that is marked as DELETED. + */ + public static final int DOI_IS_DELETED = 13; + + private int code; + + // FOR DEBUGGING + public static String codeToString(int code) { + switch (code) { + case CODE_NOT_SET: + return "CODE_NOT_SET"; + case DOI_DOES_NOT_EXIST: + return "DOI_DOES_NOT_EXSIT"; + case DOI_ALREADY_EXISTS: + return "DOI_ALREADY_EXISTS"; + case FOREIGN_DOI: + return "FOREIGN_DOI"; + case BAD_ANSWER: + return "BAD_ANSWER"; + case RESERVE_FIRST: + return "REGISTER_FIRST"; + case AUTHENTICATION_ERROR: + return "AUTHENTICATION_ERROR"; + case INTERNAL_ERROR: + return "INTERNAL_ERROR"; + case CONVERSION_ERROR: + return "CONVERSION_ERROR"; + case MISMATCH: + return "MISMATCH"; + case UNRECOGNIZED: + return "UNRECOGNIZED"; + case UNAUTHORIZED_METADATA_MANIPULATION: + return "UNAUTHORIZED_METADATA_MANIPULATION"; + case DOI_IS_DELETED: + return "DELETED"; + default: + return "UNKOWN"; + } + } + + public DOIIdentifierException() { + super(); + this.code = this.CODE_NOT_SET; + } + + public DOIIdentifierException(int code) { + super(); + this.code = code; + } + + public DOIIdentifierException(String message) { + super(message); + this.code = this.CODE_NOT_SET; + } + + public DOIIdentifierException(String message, int code) { + super(message); + this.code = code; + } + + public DOIIdentifierException(String message, Throwable cause) { + super(message, cause); + this.code = this.CODE_NOT_SET; + } + + public DOIIdentifierException(String message, Throwable cause, int code) { + super(message, cause); + this.code = code; + } + + public DOIIdentifierException(Throwable cause) { + super(cause); + this.code = this.CODE_NOT_SET; + } + + public DOIIdentifierException(Throwable cause, int code) { + super(cause); + this.code = code; + } + + public int getCode() + { + return this.code; + } + + public String getMessage() + { + String message = super.getMessage(); + if ((message == null || message.isEmpty()) && code != CODE_NOT_SET) + { + return codeToString(code); + } + return message; + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java new file mode 100644 index 0000000000000000000000000000000000000000..fa85c0abcd7eab536d5f33ce5786dc43ca20ad37 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DOIOrganiser.java @@ -0,0 +1,936 @@ +/** + * 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.identifier.doi; + +import java.io.IOException; +import java.io.PrintStream; +import java.sql.SQLException; +import java.util.Date; +import java.util.Locale; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionBuilder; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; +import org.apache.log4j.Logger; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +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.handle.HandleManager; +import org.dspace.identifier.DOI; +import org.dspace.identifier.DOIIdentifierProvider; +import org.dspace.identifier.IdentifierException; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.dspace.storage.rdbms.TableRowIterator; +import org.dspace.utils.DSpace; + + +/** + * + * @author Marsa Haoua + * @author Pascal-Nicolas Becker + */ +public class DOIOrganiser { + + private static final Logger LOG = Logger.getLogger(DOIOrganiser.class); + + private DOIIdentifierProvider provider; + private Context context; + private boolean quiet; + + public DOIOrganiser(Context context, DOIIdentifierProvider provider) + { + this.context = context; + this.provider = provider; + this.quiet = false; + } + + public static void main(String[] args) + { + LOG.debug("Starting DOI organiser "); + + // setup Context + Context context = null; + try { + context = new Context(); + } + catch (SQLException sqle) + { + System.err.println("Can't connect to database: " + sqle.getMessage()); + System.exit(-1); + } + // Started from commandline, don't use the authentication system. + context.turnOffAuthorisationSystem(); + + DOIOrganiser organiser = new DOIOrganiser(context, new DSpace().getSingletonService(DOIIdentifierProvider.class)); + + // run command line interface + runCLI(context, organiser, args); + + try + { + context.complete(); + } + catch (SQLException sqle) + { + System.err.println("Cannot save changes to database: " + sqle.getMessage()); + System.exit(-1); + } + + } + + public static void runCLI(Context context, DOIOrganiser organiser, String[] args) + { + // initlize options + Options options = new Options(); + + options.addOption("h", "help", false, "Help"); + options.addOption("l", "list", false, + "List all objects to be reserved, registered, deleted of updated "); + options.addOption("r", "register-all", false, + "Perform online registration for all identifiers queued for registration."); + options.addOption("s", "reserve-all", false, + "Perform online reservation for all identifiers queued for reservation."); + options.addOption("u", "update-all", false, + "Perform online metadata update for all identifiers queued for metadata update."); + options.addOption("d", "delete-all", false, + "Perform online deletion for all identifiers queued for deletion."); + + options.addOption("q", "quiet", false, + "Turn the command line output off."); + + Option registerDoi = OptionBuilder.withArgName("DOI|ItemID|handle") + .withLongOpt("register-doi") + .hasArgs(1) + .withDescription("Register a specified identifier. " + + "You can specify the identifier by ItemID, Handle or DOI.") + .create(); + + options.addOption(registerDoi); + + Option reserveDoi = OptionBuilder.withArgName("DOI|ItemID|handle") + .withLongOpt("reserve-doi") + .hasArgs(1) + .withDescription("Reserve a specified identifier online. " + + "You can specify the identifier by ItemID, Handle or DOI.") + .create(); + + options.addOption(reserveDoi); + + Option update = OptionBuilder.withArgName("DOI|ItemID|handle") + .hasArgs(1) + .withDescription("Update online an object for a given DOI identifier" + + " or ItemID or Handle. A DOI identifier or an ItemID or a Handle is needed.\n") + .withLongOpt("update-doi") + .create(); + + options.addOption(update); + + Option delete = OptionBuilder.withArgName("DOI identifier") + .withLongOpt("delete-doi") + .hasArgs(1) + .withDescription("Delete a specified identifier.") + .create(); + + options.addOption(delete); + + + // initialize parser + CommandLineParser parser = new PosixParser(); + CommandLine line = null; + HelpFormatter helpformater = new HelpFormatter(); + + try + { + line = parser.parse(options, args); + } + catch (ParseException ex) + { + LOG.fatal(ex); + System.exit(1); + } + + + // process options + // user asks for help + if (line.hasOption('h') || 0 == line.getOptions().length) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + + if (line.hasOption('q')) + { + organiser.setQuiet(); + } + + if (line.hasOption('l')) + { + organiser.list("reservation", null, null, DOIIdentifierProvider.TO_BE_RESERVERED); + organiser.list("registration", null, null, DOIIdentifierProvider.TO_BE_REGISTERED); + organiser.list("update", null, null, + DOIIdentifierProvider.UPDATE_BEFORE_REGISTERATION, + DOIIdentifierProvider.UPDATE_REGISTERED, + DOIIdentifierProvider.UPDATE_RESERVERED); + organiser.list("deletion", null, null, DOIIdentifierProvider.TO_BE_DELETED); + } + + if (line.hasOption('s')) + { + TableRowIterator it = organiser + .getDOIsByStatus(DOIIdentifierProvider.TO_BE_RESERVERED); + + try { + if (!it.hasNext()) + { + System.err.println("There are no objects in the database " + + "that could be reserved."); + } + + while (it.hasNext()) + { + TableRow doiRow = it.next(); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.reserve(doiRow, dso); + } + } catch (SQLException ex) { + System.err.println("Error in database connection:" + ex.getMessage()); + ex.printStackTrace(System.err); + } + } + + if (line.hasOption('r')) + { + TableRowIterator it = organiser + .getDOIsByStatus(DOIIdentifierProvider.TO_BE_REGISTERED); + + try { + if (!it.hasNext()) + { + System.err.println("There are no objects in the database " + + "that could be registered."); + } + while (it.hasNext()) + { + TableRow doiRow = it.next(); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.register(doiRow, dso); + } + } catch (SQLException ex) { + System.err.println("Error in database connection:" + ex.getMessage()); + ex.printStackTrace(System.err); + } + } + + if (line.hasOption('u')) + { + TableRowIterator it = organiser.getDOIsByStatus( + DOIIdentifierProvider.UPDATE_BEFORE_REGISTERATION, + DOIIdentifierProvider.UPDATE_RESERVERED, + DOIIdentifierProvider.UPDATE_REGISTERED); + + try { + if (!it.hasNext()) + { + System.err.println("There are no objects in the database " + + "whose metadata needs an update."); + } + + while (it.hasNext()) + { + TableRow doiRow = it.next(); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.update(doiRow, dso); + } + } catch (SQLException ex) { + System.err.println("Error in database connection:" + ex.getMessage()); + ex.printStackTrace(System.err); + } + } + + if (line.hasOption('d')) + { + TableRowIterator it = organiser + .getDOIsByStatus(DOIIdentifierProvider.TO_BE_DELETED); + + try { + if (!it.hasNext()) + { + System.err.println("There are no objects in the database " + + "that could be deleted."); + } + + while (it.hasNext()) + { + TableRow doiRow = it.next(); + organiser.delete(doiRow.getStringColumn("doi")); + } + } catch (SQLException ex) { + System.err.println("Error in database connection:" + ex.getMessage()); + ex.printStackTrace(System.err); + } + } + + + if(line.hasOption("reserve-doi")) + { + String identifier = line.getOptionValue("reserve-doi"); + + if(null == identifier) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + else + { + try { + TableRow doiRow = organiser.findTableRow(identifier); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.reserve(doiRow, dso); + } + catch (SQLException ex) + { + LOG.error(ex); + } + catch (IllegalArgumentException ex) + { + LOG.error(ex); + } + catch (IllegalStateException ex) + { + LOG.error(ex); + } catch (IdentifierException ex) { + LOG.error(ex); + } + } + } + + if(line.hasOption("register-doi")) + { + String identifier = line.getOptionValue("register-doi"); + + if(null == identifier) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + else + { + try { + TableRow doiRow = organiser.findTableRow(identifier); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.register(doiRow, dso); + } catch (SQLException ex) { + LOG.error(ex); + } catch (IllegalArgumentException ex) { + LOG.error(ex); + } catch (IllegalStateException ex) { + LOG.error(ex); + } catch (IdentifierException ex) { + LOG.error(ex); + } + } + } + + if(line.hasOption("update-doi")) + { + String identifier = line.getOptionValue('u'); + + if(null == identifier) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + else + { + try { + TableRow doiRow = organiser.findTableRow(identifier); + DSpaceObject dso = DSpaceObject.find( + context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + organiser.update(doiRow, dso); + } catch (SQLException ex) { + LOG.error(ex); + } catch (IllegalArgumentException ex) { + LOG.error(ex); + } catch (IllegalStateException ex) { + LOG.error(ex); + } catch (IdentifierException ex) { + LOG.error(ex); + } + } + } + + if(line.hasOption("delete-doi")) + { + String identifier = line.getOptionValue('d'); + + if (null == identifier) + { + helpformater.printHelp("\nDOI organiser\n", options); + } + else { + try { + organiser.delete(identifier); + } catch (SQLException ex) { + LOG.error(ex); + } catch (IllegalArgumentException ex) { + LOG.error(ex); + } + } + } + + } + + + public TableRowIterator getDOIsByStatus(Integer ... status) + { + try + { + String sql = "SELECT * FROM Doi"; + for (int i = 0; i < status.length ; i++) + { + if (0 == i) + { + sql += " WHERE "; + } + else + { + sql += " OR "; + } + sql += " status = ?"; + } + + if (status.length < 1) + { + return DatabaseManager.queryTable(context, "Doi", sql); + } + return DatabaseManager.queryTable(context, "Doi", sql, status); + } + catch (SQLException ex) + { + LOG.error("Error while trying to get data from database", ex); + throw new RuntimeException("Error while trying to get data from database", ex); + } + } + + public void list(String processName, PrintStream out, PrintStream err, Integer ... status) + { + String indent = " "; + if (null == out) + { + out = System.out; + } + if (null == err) + { + err = System.err; + } + + TableRowIterator it = this.getDOIsByStatus(status); + + try + { + if (it.hasNext()) + { + out.println("DOIs queued for " + processName + ": "); + } + else + { + out.println("There are no DOIs queued for " + processName + "."); + } + while(it.hasNext()) + { + TableRow doiRow = it.next(); + DSpaceObject dso = DSpaceObject.find(context, + doiRow.getIntColumn("resource_type_id"), + doiRow.getIntColumn("resource_id")); + out.print(indent + DOI.SCHEME + doiRow.getStringColumn("doi")); + if (null != dso) + { + out.println(" (belongs to item with handle " + dso.getHandle() + ")"); + } + else + { + out.println(" (cannot determine handle of assigned object)"); + } + } + out.println(""); + } + catch (SQLException ex) + { + err.println("Error in database Connection: " + ex.getMessage()); + ex.printStackTrace(err); + } + finally + { + it.close(); + } + } + + public void register(TableRow doiRow, DSpaceObject dso) throws SQLException + { + if (Constants.ITEM != dso.getType()) + { + throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only."); + } + + try { + provider.registerOnline(context, dso, + DOI.SCHEME + doiRow.getStringColumn("doi")); + + if(!quiet) + { + System.out.println("This identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " is successfully registered."); + } + } + catch (IdentifierException ex) + { + if (!(ex instanceof DOIIdentifierException)) + { + LOG.error("It wasn't possible to register this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " online. ", ex); + } + + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + + try + { + sendAlertMail("Register", dso, + DOI.SCHEME + doiRow.getStringColumn("doi"), + doiIdentifierException.codeToString(doiIdentifierException + .getCode())); + } + catch (IOException ioe) + { + LOG.error("Couldn't send mail", ioe); + } + + LOG.error("It wasn't possible to register this identifier : " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " online. Exceptions code: " + + doiIdentifierException + .codeToString(doiIdentifierException.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to register this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + + } + catch (IllegalArgumentException ex) + { + LOG.error("Database table DOI contains a DOI that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + + if(!quiet) + { + System.err.println("It wasn't possible to register this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + + throw new IllegalStateException("Database table DOI contains a DOI " + + " that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + } + catch (SQLException ex) + { + LOG.error("Error while trying to get data from database", ex); + + if(!quiet) + { + System.err.println("It wasn't possible to register this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + throw new RuntimeException("Error while trying to get data from database", ex); + } + } + + public void reserve(TableRow doiRow, DSpaceObject dso) throws SQLException + { + if (Constants.ITEM != dso.getType()) + { + throw new IllegalArgumentException("Currenty DSpace supports DOIs for Items only."); + } + + try + { + provider.reserveOnline(context, dso, + DOI.SCHEME + doiRow.getStringColumn("doi")); + + if(!quiet) + { + System.out.println("This identifier : " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " is successfully reserved."); + } + } + catch (IdentifierException ex) + { + if (!(ex instanceof DOIIdentifierException)) + { + LOG.error("It wasn't possible to register this identifier : " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " online. ",ex); + } + + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + + try + { + sendAlertMail("Reserve", dso, + DOI.SCHEME + doiRow.getStringColumn("doi"), + DOIIdentifierException.codeToString( + doiIdentifierException.getCode())); + } + catch (IOException ioe) + { + LOG.error("Couldn't send mail", ioe); + } + + LOG.error("It wasn't possible to reserve the identifier online. " + + " Exceptions code: " + + DOIIdentifierException + .codeToString(doiIdentifierException.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to reserve this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + } + catch (IllegalArgumentException ex) + { + LOG.error("Database table DOI contains a DOI that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + + if(!quiet) + { + System.err.println("It wasn't possible to reserve this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + throw new IllegalStateException("Database table DOI contains a DOI " + + " that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + } + catch (SQLException ex) + { + LOG.error("Error while trying to get data from database", ex); + + if(!quiet) + { + System.err.println("It wasn't possible to reserve this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + throw new RuntimeException("Error while trying to get data from database", ex); + + } + } + + public void update(TableRow doiRow, DSpaceObject dso) + { + if (Constants.ITEM != dso.getType()) + { + throw new IllegalArgumentException("Currenty DSpace supports DOIs " + + "for Items only."); + } + + try + { + provider.updateMetadataOnline(context, dso, + DOI.SCHEME + doiRow.getStringColumn("doi")); + + if(!quiet) + { + System.out.println("Successfully updated metadata of DOI " + DOI.SCHEME + + doiRow.getStringColumn("doi") + "."); + } + } + catch (IdentifierException ex) + { + if (!(ex instanceof DOIIdentifierException)) + { + LOG.error("It wasn't possible to register the identifier online. ",ex); + } + + DOIIdentifierException doiIdentifierException = (DOIIdentifierException) ex; + + try + { + sendAlertMail("Update", dso, + DOI.SCHEME + doiRow.getStringColumn("doi"), + doiIdentifierException.codeToString(doiIdentifierException + .getCode())); + } + catch (IOException ioe) + { + LOG.error("Couldn't send mail", ioe); + } + + LOG.error("It wasn't possible to update this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " Exceptions code: " + + doiIdentifierException + .codeToString(doiIdentifierException.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to update this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + + } + catch (IllegalArgumentException ex) + { + LOG.error("Database table DOI contains a DOI that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + + if(!quiet) + { + System.err.println("It wasn't possible to update this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + + throw new IllegalStateException("Database table DOI contains a DOI " + + " that is not valid: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + "!", ex); + } + catch (SQLException ex) + { + LOG.error("It wasn't possible to connect to the Database!", ex); + } + } + + public void delete(String identifier) + throws SQLException + { + String doi = null; + TableRow doiRow = null; + + try + { + doi = DOI.formatIdentifier(identifier); + + // If there's no exception: we found a valid DOI. :) + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + + if (null == doiRow) + { + throw new IllegalStateException("You specified a valid DOI," + + " that is not stored in our database."); + } + provider.deleteOnline(context, doi); + + if (!quiet) + { + System.err.println("It was possible to delete this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " online."); + } + } + catch (DOIIdentifierException ex) + { + // Identifier was not recognized as DOI. + LOG.error("It wasn't possible to detect this identifier: " + + identifier + + " Exceptions code: " + + ex.codeToString(ex.getCode()), ex); + + if (!quiet) + { + System.err.println("It wasn't possible to detect this identifier: " + + identifier); + } + } + catch (IllegalArgumentException ex) + { + if (!quiet) + { + System.err.println("It wasn't possible to delete this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi") + + " online. Take a look in log file."); + } + } + } + + /** + * Finds the TableRow in the Doi table that belongs to the specified + * DspaceObject. + * + * @param identifier Either an ItemID, a DOI or a handle. If the identifier + * contains digits only we treat it as ItemID, if not we try to find a + * matching doi or a handle (in this order). + * @return The TableRow or null if the Object does not have a DOI. + * @throws SQLException + * @throws IllegalArgumentException If the identifier is null, an empty + * String or specifies an DSpaceObject that is not an item. We currently + * support DOIs for items only, but this may change once... + * @throws IllegalStateException If the identifier was a valid DOI that is + * not stored in our database or if it is a handle that is not bound to an + * DSpaceObject. + */ + public TableRow findTableRow(String identifier) + throws SQLException, IllegalArgumentException, IllegalStateException, IdentifierException + { + if (null == identifier || identifier.isEmpty()) + { + throw new IllegalArgumentException("Identifier is null or empty."); + } + + String sql = "SELECT * FROM Doi WHERE resource_type_id = ? AND resource_id = ? "; + TableRow doiRow = null; + String doi = null; + + // detect it identifer is ItemID, handle or DOI. + // try to detect ItemID + if (identifier.matches("\\d*")) + { + Integer itemID = Integer.valueOf(identifier); + DSpaceObject dso = Item.find(context, itemID); + + if (null != dso) + { + doiRow = DatabaseManager.querySingleTable(context, "Doi", + sql, Constants.ITEM, dso.getID()); + + //Check if this Item has an Identifier, mint one if it doesn't + if (null == doiRow) + { + doi = provider.mint(context, dso); + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + return doiRow; + } + return doiRow; + } + else + { + throw new IllegalStateException("You specified an ItemID, " + + "that is not stored in our database."); + } + } + + // detect handle + DSpaceObject dso = HandleManager.resolveToObject(context, identifier); + + if (null != dso) + { + if (dso.getType() != Constants.ITEM) + { + throw new IllegalArgumentException( + "Currently DSpace supports DOIs for Items only. " + + "Cannot process specified handle as it does not identify an Item."); + } + + doiRow = DatabaseManager.querySingleTable(context, "Doi", sql, + Constants.ITEM, dso.getID()); + + if (null == doiRow) + { + doi = provider.mint(context, dso); + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + } + return doiRow; + } + // detect DOI + try { + doi = DOI.formatIdentifier(identifier); + // If there's no exception: we found a valid DOI. :) + doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + if (null == doiRow) + { + throw new IllegalStateException("You specified a valid DOI," + + " that is not stored in our database."); + } + } + catch (DOIIdentifierException ex) + { + // Identifier was not recognized as DOI. + LOG.error("It wasn't possible to detect this identifier: " + + identifier + + " Exceptions code: " + + ex.codeToString(ex.getCode()), ex); + + if(!quiet) + { + System.err.println("It wasn't possible to detect this identifier: " + + DOI.SCHEME + doiRow.getStringColumn("doi")); + } + } + + return doiRow; + } + + private void sendAlertMail(String action, DSpaceObject dso, String doi, String reason) + throws IOException + { + String recipient = ConfigurationManager.getProperty("alert.recipient"); + + try + { + if (recipient != null) + { + Email email = Email.getEmail( + I18nUtil.getEmailFilename(Locale.getDefault(), "doi_maintenance_error")); + email.addRecipient(recipient); + email.addArgument(action); + email.addArgument(new Date()); + email.addArgument(dso.getTypeText()); + email.addArgument(new Integer(dso.getID())); + email.addArgument(doi); + email.addArgument(reason); + email.send(); + + if (!quiet) + { + System.err.println("Email alert is sent."); + } + } + } + catch (Exception e) { + LOG.warn("Unable to send email alert", e); + if (!quiet) + { + System.err.println("Unable to send email alert."); + } + } + } + + private void setQuiet() + { + this.quiet = true; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..736ede53adf354d8d430fcf191a1bb6a0db04f84 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/DataCiteConnector.java @@ -0,0 +1,1066 @@ +/** + * 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.identifier.doi; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.URISyntaxException; +import java.sql.SQLException; +import java.util.Iterator; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.StatusLine; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.entity.ContentType; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.DefaultHttpClient; +import org.apache.http.util.EntityUtils; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DSpaceObject; +import org.dspace.content.crosswalk.CrosswalkException; +import org.dspace.content.crosswalk.DisseminationCrosswalk; +import org.dspace.core.Context; +import org.dspace.core.PluginManager; +import org.dspace.handle.HandleManager; +import org.dspace.identifier.DOI; +import org.dspace.services.ConfigurationService; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.filter.ElementFilter; +import org.jdom.input.SAXBuilder; +import org.jdom.output.Format; +import org.jdom.output.XMLOutputter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Required; + +/** + * + * @author Pascal-Nicolas Becker + */ +public class DataCiteConnector +implements DOIConnector +{ + + private static final Logger log = LoggerFactory.getLogger(DataCiteConnector.class); + + // Configuration property names + static final String CFG_USER = "identifier.doi.user"; + static final String CFG_PASSWORD = "identifier.doi.password"; + + /** + * Stores the scheme used to connect to the DataCite server. It will be set + * by spring dependency injection. + */ + protected String SCHEME; + /** + * Stores the hostname of the DataCite server. Set by spring dependency + * injection. + */ + protected String HOST; + + /** + * Path on the DataCite server used to generate DOIs. Set by spring + * dependency injection. + */ + protected String DOI_PATH; + /** + * Path on the DataCite server used to register metadata. Set by spring + * dependency injection. + */ + protected String METADATA_PATH; + /** + * Name of crosswalk to convert metadata into DataCite Metadata Scheme. Set + * by spring dependency injection. + */ + protected String CROSSWALK_NAME; + /** + * DisseminationCrosswalk to map local metadata into DataCite metadata. + * The name of the crosswalk is set by spring dependency injection using + * {@link setDisseminationCrosswalk(String) setDisseminationCrosswalk} which + * instantiates the crosswalk. + */ + protected DisseminationCrosswalk xwalk; + + protected ConfigurationService configurationService; + + protected String USERNAME; + protected String PASSWORD; + + public DataCiteConnector() + { + this.xwalk = null; + this.USERNAME = null; + this.PASSWORD = null; + } + + /** + * Used to set the scheme to connect the DataCite server. Used by spring + * dependency injection. + * @param DATACITE_SCHEME Probably https or http. + */ + @Required + public void setDATACITE_SCHEME(String DATACITE_SCHEME) + { + this.SCHEME = DATACITE_SCHEME; + } + + /** + * Set the hostname of the DataCite server. Used by spring dependency + * injection. + * @param DATACITE_HOST Hostname to connect to register DOIs (f.e. test.datacite.org). + */ + @Required + public void setDATACITE_HOST(String DATACITE_HOST) + { + this.HOST = DATACITE_HOST; + } + + /** + * Set the path on the DataCite server to register DOIs. Used by spring + * dependency injection. + * @param DATACITE_DOI_PATH Path to register DOIs, f.e. /doi. + */ + @Required + public void setDATACITE_DOI_PATH(String DATACITE_DOI_PATH) + { + if (!DATACITE_DOI_PATH.startsWith("/")) + { + DATACITE_DOI_PATH = "/" + DATACITE_DOI_PATH; + } + if (!DATACITE_DOI_PATH.endsWith("/")) + { + DATACITE_DOI_PATH = DATACITE_DOI_PATH + "/"; + } + + this.DOI_PATH = DATACITE_DOI_PATH; + } + + /** + * Set the path to register metadata on DataCite server. Used by spring + * dependency injection. + * @param DATACITE_METADATA_PATH Path to register metadata, f.e. /mds. + */ + @Required + public void setDATACITE_METADATA_PATH(String DATACITE_METADATA_PATH) + { + if (!DATACITE_METADATA_PATH.startsWith("/")) + { + DATACITE_METADATA_PATH = "/" + DATACITE_METADATA_PATH; + } + if (!DATACITE_METADATA_PATH.endsWith("/")) + { + DATACITE_METADATA_PATH = DATACITE_METADATA_PATH + "/"; + } + + this.METADATA_PATH = DATACITE_METADATA_PATH; + } + + + @Autowired + @Required + public void setConfigurationService(ConfigurationService configurationService) + { + this.configurationService = configurationService; + } + + /** + * Set the name of the dissemination crosswalk used to convert the metadata + * into DataCite Metadata Schema. Used by spring dependency injection. + * @param CROSSWALK_NAME The name of the dissemination crosswalk to use. This + * crosswalk must be configured in dspace.cfg. + */ + @Required + public void setDisseminationCrosswalkName(String CROSSWALK_NAME) { + this.CROSSWALK_NAME = CROSSWALK_NAME; + } + + protected void prepareXwalk() + { + if (null != this.xwalk) + return; + + this.xwalk = (DisseminationCrosswalk) PluginManager.getNamedPlugin( + DisseminationCrosswalk.class, this.CROSSWALK_NAME); + + if (this.xwalk == null) + { + throw new RuntimeException("Can't find crosswalk '" + + CROSSWALK_NAME + "'!"); + } + } + + protected String getUsername() + { + if (null == this.USERNAME) + { + this.USERNAME = this.configurationService.getProperty(CFG_USER); + if (null == this.USERNAME) + { + throw new RuntimeException("Unable to load username from " + + "configuration. Cannot find property " + + CFG_USER + "."); + } + } + return this.USERNAME; + } + + protected String getPassword() + { + if (null == this.PASSWORD) + { + this.PASSWORD = this.configurationService.getProperty(CFG_PASSWORD); + if (null == this.PASSWORD) + { + throw new RuntimeException("Unable to load password from " + + "configuration. Cannot find property " + + CFG_PASSWORD + "."); + } + } + return this.PASSWORD; + } + + + public boolean isDOIReserved(Context context, String doi) + throws DOIIdentifierException + { + return isDOIReserved(context, null, doi); + } + + @Override + public boolean isDOIReserved(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + // get mds/metadata/<doi> + DataCiteResponse resp = this.sendMetadataGetRequest(doi); + + switch (resp.getStatusCode()) + { + // 200 -> reserved + // if (200 && dso != null) -> compare url (out of response-content) with dso + case (200) : + { + // Do we check if doi is reserved generally or for a specified dso? + if (null == dso) + { + return true; + } + + // check if doi belongs to dso + String doiHandle = null; + try + { + doiHandle = extractAlternateIdentifier(context, resp.getContent()); + } + catch (SQLException e) + { + throw new RuntimeException(e); + } + + if (null == doiHandle) + { + // we were unable to find a handle belonging to our repository + return false; + } + + String dsoHandle = dso.getHandle(); + if (null == dsoHandle) + { + return false; + } + return dsoHandle.equals(doiHandle); + } + + // 404 "Not Found" means DOI is neither reserved nor registered. + case (404) : + { + return false; + } + + // 410 GONE -> DOI is set inactive + // that means metadata has been deleted + // it is unclear if the doi has been registered before or only reserved. + // it is unclear for which item it has been reserved + // we will handle this as if it reserved for an unknown object. + case (410) : + { + if (null == dso) + { + return true; + } + else + { + return false; + } + } + + // Catch all other http status code in case we forgot one. + default : + { + log.warn("While checking if the DOI {} is registered, we got a " + + "http status code {} and the message \"{}\".", + new String[] + { + doi, Integer.toString(resp.statusCode), + resp.getContent() + }); + throw new DOIIdentifierException("Unable to parse an answer from " + + "DataCite API. Please have a look into DSpace logs.", + DOIIdentifierException.BAD_ANSWER); + } + } + } + + @Override + public boolean isDOIRegistered(Context context, String doi) + throws DOIIdentifierException + { + return isDOIRegistered(context, null, doi); + } + + @Override + public boolean isDOIRegistered(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + DataCiteResponse response = sendDOIGetRequest(doi); + + switch (response.getStatusCode()) + { + // status code 200 means the doi is reserved and registered + case (200) : + { + // Do we check if doi is reserved generally or for a specified dso? + if (null == dso) + { + return true; + } + + // DataCite returns the URL the DOI currently points to. + // To ensure that the DOI is registered for a specified dso it + // should be sufficient to compare the URL DataCite returns with + // the URL of the dso. + String doiUrl = response.getContent(); + if (null == doiUrl) + { + log.error("Received a status code 200 without a response content. DOI: {}.", doi); + throw new DOIIdentifierException("Received a http status code 200 without a response content.", + DOIIdentifierException.BAD_ANSWER); + } + + String dsoUrl = null; + try + { + dsoUrl = HandleManager.resolveToURL(context, dso.getHandle()); + } + catch (SQLException e) + { + log.error("Error in database connection: " + e.getMessage()); + throw new RuntimeException(e); + } + + if (null == dsoUrl) + { + // the handle of the dso was not found in our db?! + log.error("The HandleManager was unable to find the handle " + + "of a DSpaceObject in the database!?! " + + "Type: {} ID: {}", dso.getTypeText(), dso.getID()); + throw new RuntimeException("The HandleManager was unable to " + + "find the handle of a DSpaceObject in the database!"); + } + + return (dsoUrl.equals(doiUrl)); + } + // Status Code 204 "No Content" stands for a known DOI without URL. + // A DOI that is known but does not have any associated URL is + // reserved but not registered yet. + case (204) : + { + // we know it is reserved, but we do not know for which object. + // won't add this to the cache. + return false; + } + // 404 "Not Found" means DOI is neither reserved nor registered. + case (404) : + { + return false; + } + // Catch all other http status code in case we forgot one. + default : + { + log.warn("While checking if the DOI {} is registered, we got a " + + "http status code {} and the message \"{}\".", + new String[] {doi, Integer.toString(response.statusCode), response.getContent()}); + throw new DOIIdentifierException("Unable to parse an answer from " + + "DataCite API. Please have a look into DSpace logs.", + DOIIdentifierException.BAD_ANSWER); + } + } + } + + + @Override + public void deleteDOI(Context context, String doi) + throws DOIIdentifierException + { + if (!isDOIReserved(context, doi)) + return; + + // delete mds/metadata/<doi> + DataCiteResponse resp = this.sendMetadataDeleteRequest(doi); + switch(resp.getStatusCode()) + { + //ok + case (200) : + { + return; + } + // 404 "Not Found" means DOI is neither reserved nor registered. + case (404) : + { + log.error("DOI {} is at least reserved, but a delete request " + + "told us that it is unknown!", doi); + return; + } + // Catch all other http status code in case we forgot one. + default : + { + log.warn("While deleting metadata of DOI {}, we got a " + + "http status code {} and the message \"{}\".", + new String[] {doi, Integer.toString(resp.statusCode), resp.getContent()}); + throw new DOIIdentifierException("Unable to parse an answer from " + + "DataCite API. Please have a look into DSpace logs.", + DOIIdentifierException.BAD_ANSWER); + } + } + } + + @Override + public void reserveDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + // check if DOI is reserved at the registration agency + if (this.isDOIReserved(context, doi)) + { + // if doi is registered for this object we still should check its + // status in our database (see below). + // if it is registered for another object we should notify an admin + if (!this.isDOIReserved(context, dso, doi)) + { + log.warn("DOI {} is reserved for another object already.", doi); + throw new DOIIdentifierException(DOIIdentifierException.DOI_ALREADY_EXISTS); + } + // the DOI is reserved for this Object. We use {@code reserveDOI} to + // send metadata updates, so don't return here! + } + + this.prepareXwalk(); + + if (!this.xwalk.canDisseminate(dso)) + { + log.error("Crosswalk " + this.CROSSWALK_NAME + + " cannot disseminate DSO with type " + dso.getType() + + " and ID " + dso.getID() + ". Giving up reserving the DOI " + + doi + "."); + throw new DOIIdentifierException("Cannot disseminate " + + dso.getTypeText() + "/" + dso.getID() + + " using crosswalk " + this.CROSSWALK_NAME + ".", + DOIIdentifierException.CONVERSION_ERROR); + } + + Element root = null; + try + { + root = xwalk.disseminateElement(dso); + } + catch (AuthorizeException ae) + { + log.error("Caught an AuthorizeException while disseminating DSO " + + "with type " + dso.getType() + " and ID " + dso.getID() + + ". Giving up to reserve DOI " + doi + ".", ae); + throw new DOIIdentifierException("AuthorizeException occured while " + + "converting " + dso.getTypeText() + "/" + dso.getID() + + " using crosswalk " + this.CROSSWALK_NAME + ".", ae, + DOIIdentifierException.CONVERSION_ERROR); + } + catch (CrosswalkException ce) + { + log.error("Caught an CrosswalkException while reserving a DOI (" + + doi + ") for DSO with type " + dso.getType() + " and ID " + + dso.getID() + ". Won't reserve the doi.", ce); + throw new DOIIdentifierException("CrosswalkException occured while " + + "converting " + dso.getTypeText() + "/" + dso.getID() + + " using crosswalk " + this.CROSSWALK_NAME + ".", ce, + DOIIdentifierException.CONVERSION_ERROR); + } + catch (IOException ioe) + { + throw new RuntimeException(ioe); + } + catch (SQLException se) + { + throw new RuntimeException(se); + } + + String metadataDOI = extractDOI(root); + if (null == metadataDOI) + { + // The DOI will be saved as metadata of dso after successful + // registration. To register a doi it has to be part of the metadata + // sent to DataCite. So we add it to the XML we'll send to DataCite + // and we'll add it to the DSO after successful registration. + root = addDOI(doi, root); + } + else if (!metadataDOI.equals(doi.substring(DOI.SCHEME.length()))) + { + // FIXME: that's not an error. If at all, it is worth logging it. + throw new DOIIdentifierException("DSO with type " + dso.getTypeText() + + " and id " + dso.getID() + " already has DOI " + + metadataDOI + ". Won't reserve DOI " + doi + " for it."); + } + + // send metadata as post to mds/metadata + DataCiteResponse resp = this.sendMetadataPostRequest(doi, root); + + switch (resp.getStatusCode()) + { + // 201 -> created / ok + case (201) : + { + return; + } + // 400 -> invalid XML + case (400) : + { + log.warn("DataCite was unable to understand the XML we send."); + log.warn("DataCite Metadata API returned a http status code " + +"400: " + resp.getContent()); + Format format = Format.getCompactFormat(); + format.setEncoding("UTF-8"); + XMLOutputter xout = new XMLOutputter(format); + log.info("We send the following XML:\n" + xout.outputString(root)); + throw new DOIIdentifierException("Unable to reserve DOI " + doi + + ". Please inform your administrator or take a look " + +" into the log files.", DOIIdentifierException.BAD_REQUEST); + } + // Catch all other http status code in case we forgot one. + default : + { + log.warn("While reserving the DOI {}, we got a http status code " + + "{} and the message \"{}\".", new String[] + {doi, Integer.toString(resp.statusCode), resp.getContent()}); + throw new DOIIdentifierException("Unable to parse an answer from " + + "DataCite API. Please have a look into DSpace logs.", + DOIIdentifierException.BAD_ANSWER); + } + } + } + + @Override + public void registerDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + // check if the DOI is already registered online + if (this.isDOIRegistered(context, doi)) + { + // if it is registered for another object we should notify an admin + if (!this.isDOIRegistered(context, dso, doi)) + { + // DOI is reserved for another object + log.warn("DOI {} is registered for another object already.", doi); + throw new DOIIdentifierException(DOIIdentifierException.DOI_ALREADY_EXISTS); + } + // doi is registered for this object, we're done + return; + } + else + { + // DataCite wants us to reserve a DOI before we can register it + if (!this.isDOIReserved(context, dso, doi)) + { + // check if doi is already reserved for another dso + if (this.isDOIReserved(context, doi)) + { + log.warn("Trying to register DOI {}, that is reserved for " + + "another dso.", doi); + throw new DOIIdentifierException("Trying to register a DOI " + + "that is reserved for another object.", + DOIIdentifierException.DOI_ALREADY_EXISTS); + } + + // the DOIIdentifierProvider should catch and handle this + throw new DOIIdentifierException("You need to reserve a DOI " + + "before you can register it.", + DOIIdentifierException.RESERVE_FIRST); + } + } + + // send doi=<doi>\nurl=<url> to mds/doi + DataCiteResponse resp = null; + try + { + resp = this.sendDOIPostRequest(doi, + HandleManager.resolveToURL(context, dso.getHandle())); + } + catch (SQLException e) + { + log.error("Caught SQL-Exception while resolving handle to URL: " + + e.getMessage()); + throw new RuntimeException(e); + } + + switch(resp.statusCode) + { + // 201 -> created/updated -> okay + case (201) : + { + return; + } + // 400 -> wrong domain, wrong prefix, wrong request body + case (400) : + { + log.warn("We send an irregular request to DataCite. While " + + "registering a DOI they told us: " + resp.getContent()); + throw new DOIIdentifierException("Currently we cannot register " + + "DOIs. Please inform the administrator or take a look " + + " in the DSpace log file.", + DOIIdentifierException.BAD_REQUEST); + } + // 412 Precondition failed: DOI was not reserved before registration! + case (412) : + { + log.error("We tried to register a DOI {} that was not reserved " + + "before! The registration agency told us: {}.", doi, + resp.getContent()); + throw new DOIIdentifierException("There was an error in handling " + + "of DOIs. The DOI we wanted to register had not been " + + "reserved in advance. Please contact the administrator " + + "or take a look in DSpace log file.", + DOIIdentifierException.RESERVE_FIRST); + } + // Catch all other http status code in case we forgot one. + default : + { + log.warn("While registration of DOI {}, we got a http status code " + + "{} and the message \"{}\".", new String[] + {doi, Integer.toString(resp.statusCode), resp.getContent()}); + throw new DOIIdentifierException("Unable to parse an answer from " + + "DataCite API. Please have a look into DSpace logs.", + DOIIdentifierException.BAD_ANSWER); + } + } + } + + @Override + public void updateMetadata(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + // check if doi is reserved for another object + if (!this.isDOIReserved(context, dso, doi) && this.isDOIReserved(context, doi)) + { + log.warn("Trying to update metadata for DOI {}, that is reserved" + + " for another dso.", doi); + throw new DOIIdentifierException("Trying to update metadta for " + + "a DOI that is reserved for another object.", + DOIIdentifierException.DOI_ALREADY_EXISTS); + } + // We can use reserveDOI to update metadata. Datacite API uses the same + // request for reservartion as for updating metadata. + this.reserveDOI(context, dso, doi); + } + + protected DataCiteResponse sendDOIPostRequest(String doi, String url) + throws DOIIdentifierException + { + // post mds/doi/ + // body must contaion "doi=<doi>\nurl=<url>}n" + URIBuilder uribuilder = new URIBuilder(); + uribuilder.setScheme(SCHEME).setHost(HOST).setPath(DOI_PATH); + + HttpPost httppost = null; + try + { + httppost = new HttpPost(uribuilder.build()); + } + catch (URISyntaxException e) + { + log.error("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!"); + log.error("The URL was {}.", SCHEME + "://" + HOST + + DOI_PATH + "/" + doi.substring(DOI.SCHEME.length())); + throw new RuntimeException("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!", e); + } + + // assemble request content: + HttpEntity reqEntity = null; + try + { + String req = "doi=" + doi.substring(DOI.SCHEME.length()) + "\n" + "url=" + url + "\n"; + ContentType contentType = ContentType.create("text/plain", "UTF-8"); + reqEntity = new StringEntity(req, contentType); + httppost.setEntity(reqEntity); + + return sendHttpRequest(httppost, doi); + } + finally + { + // release ressources + try + { + EntityUtils.consume(reqEntity); + } + catch (IOException ioe) + { + log.info("Caught an IOException while releasing a HTTPEntity:" + + ioe.getMessage()); + } + } + } + + + protected DataCiteResponse sendMetadataDeleteRequest(String doi) + throws DOIIdentifierException + { + // delete mds/metadata/<doi> + URIBuilder uribuilder = new URIBuilder(); + uribuilder.setScheme(SCHEME).setHost(HOST).setPath(METADATA_PATH + + doi.substring(DOI.SCHEME.length())); + + HttpDelete httpdelete = null; + try + { + httpdelete = new HttpDelete(uribuilder.build()); + } + catch (URISyntaxException e) + { + log.error("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!"); + log.error("The URL was {}.", SCHEME + "://" + HOST + + DOI_PATH + "/" + doi.substring(DOI.SCHEME.length())); + throw new RuntimeException("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!", e); + } + return sendHttpRequest(httpdelete, doi); + } + + protected DataCiteResponse sendDOIGetRequest(String doi) + throws DOIIdentifierException + { + return sendGetRequest(doi, DOI_PATH); + } + + protected DataCiteResponse sendMetadataGetRequest(String doi) + throws DOIIdentifierException + { + return sendGetRequest(doi, METADATA_PATH); + } + + protected DataCiteResponse sendGetRequest(String doi, String path) + throws DOIIdentifierException + { + URIBuilder uribuilder = new URIBuilder(); + uribuilder.setScheme(SCHEME).setHost(HOST).setPath(path + + doi.substring(DOI.SCHEME.length())); + + HttpGet httpget = null; + try + { + httpget = new HttpGet(uribuilder.build()); + } + catch (URISyntaxException e) + { + log.error("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!"); + log.error("The URL was {}.", SCHEME + "://" + HOST + + DOI_PATH + "/" + doi.substring(DOI.SCHEME.length())); + throw new RuntimeException("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!", e); + } + return sendHttpRequest(httpget, doi); + } + + protected DataCiteResponse sendMetadataPostRequest(String doi, Element metadataRoot) + throws DOIIdentifierException + { + Format format = Format.getCompactFormat(); + format.setEncoding("UTF-8"); + XMLOutputter xout = new XMLOutputter(format); + return sendMetadataPostRequest(doi, xout.outputString(new Document(metadataRoot))); + } + + protected DataCiteResponse sendMetadataPostRequest(String doi, String metadata) + throws DOIIdentifierException + { + // post mds/metadata/ + // body must contain metadata in DataCite-XML. + URIBuilder uribuilder = new URIBuilder(); + uribuilder.setScheme(SCHEME).setHost(HOST).setPath(METADATA_PATH); + + HttpPost httppost = null; + try + { + httppost = new HttpPost(uribuilder.build()); + } + catch (URISyntaxException e) + { + log.error("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!"); + log.error("The URL was {}.", SCHEME + "://" + HOST + + DOI_PATH + "/" + doi.substring(DOI.SCHEME.length())); + throw new RuntimeException("The URL we constructed to check a DOI " + + "produced a URISyntaxException. Please check the configuration parameters!", e); + } + + // assemble request content: + HttpEntity reqEntity = null; + try + { + ContentType contentType = ContentType.create("application/xml", "UTF-8"); + reqEntity = new StringEntity(metadata, contentType); + httppost.setEntity(reqEntity); + + return sendHttpRequest(httppost, doi); + } + finally + { + // release ressources + try + { + EntityUtils.consume(reqEntity); + } + catch (IOException ioe) + { + log.info("Caught an IOException while releasing an HTTPEntity:" + + ioe.getMessage()); + } + } + } + + /** + * + * @param req + * @param doi + * @return + * @throws DOIIdentifierException + */ + protected DataCiteResponse sendHttpRequest(HttpUriRequest req, String doi) + throws DOIIdentifierException + { + DefaultHttpClient httpclient = new DefaultHttpClient(); + httpclient.getCredentialsProvider().setCredentials( + new AuthScope(HOST, 443), + new UsernamePasswordCredentials(this.getUsername(), this.getPassword())); + + HttpEntity entity = null; + try + { + HttpResponse response = httpclient.execute(req); + + StatusLine status = response.getStatusLine(); + int statusCode = status.getStatusCode(); + + String content = null; + entity = response.getEntity(); + if (null != entity) + { + content = EntityUtils.toString(entity, "UTF-8"); + } + + /* While debugging it can be useful to see whitch requests are send: + * + * log.debug("Going to send HTTP request of type " + req.getMethod() + "."); + * log.debug("Will be send to " + req.getURI().toString() + "."); + * if (req instanceof HttpEntityEnclosingRequestBase) + * { + * log.debug("Request contains entity!"); + * HttpEntityEnclosingRequestBase reqee = (HttpEntityEnclosingRequestBase) req; + * if (reqee.getEntity() instanceof StringEntity) + * { + * StringEntity se = (StringEntity) reqee.getEntity(); + * try { + * BufferedReader br = new BufferedReader(new InputStreamReader(se.getContent())); + * String line = null; + * while ((line = br.readLine()) != null) + * { + * log.debug(line); + * } + * log.info("----"); + * } catch (IOException ex) { + * + * } + * } + * } else { + * log.debug("Request contains no entity!"); + * } + * log.debug("The request got http status code {}.", Integer.toString(statusCode)); + * if (null == content) + * { + * log.debug("The response did not contain any answer."); + * } else { + * log.debug("DataCite says: {}", content); + * } + * + */ + + // We can handle some status codes here, others have to be handled above + switch (statusCode) + { + // we get a 401 if we forgot to send credentials or if the username + // and password did not match. + case (401) : + { + log.info("We were unable to authenticate against the DOI registry agency."); + log.info("The response was: {}", content); + throw new DOIIdentifierException("Cannot authenticate at the " + + "DOI registry agency. Please check if username " + + "and password are set correctly.", + DOIIdentifierException.AUTHENTICATION_ERROR); + } + + // We get a 403 Forbidden if we are managing a DOI that belongs to + // another party or if there is a login problem. + case (403) : + { + log.info("Managing a DOI ({}) was prohibited by the DOI " + + "registration agency: {}", doi, content); + throw new DOIIdentifierException("We can check, register or " + + "reserve DOIs that belong to us only.", + DOIIdentifierException.FOREIGN_DOI); + } + + + // 500 is documented and signals an internal server error + case (500) : + { + log.warn("Caught an http status code 500 while managing DOI " + +"{}. Message was: " + content); + throw new DOIIdentifierException("DataCite API has an internal error. " + + "It is temporarily impossible to manage DOIs. " + + "Further information can be found in DSpace log file.", + DOIIdentifierException.INTERNAL_ERROR); + } + } + + + return new DataCiteResponse(statusCode, content); + } + catch (IOException e) + { + log.warn("Caught an IOException: " + e.getMessage()); + throw new RuntimeException(e); + } + finally + { + try + { + // Release any ressources used by HTTP-Request. + if (null != entity) + { + EntityUtils.consume(entity); + } + } + catch (IOException e) + { + log.warn("Can't release HTTP-Entity: " + e.getMessage()); + } + } + } + + // returns null or handle + protected String extractAlternateIdentifier(Context context, String content) + throws SQLException, DOIIdentifierException + { + if (content == null) + { + return null; + } + + // parse the XML + SAXBuilder saxBuilder = new SAXBuilder(); + Document doc = null; + try + { + doc = saxBuilder.build(new ByteArrayInputStream(content.getBytes("UTF-8"))); + } + catch (IOException ioe) + { + throw new RuntimeException("Got an IOException while reading from a string?!", ioe); + } + catch (JDOMException jde) + { + throw new DOIIdentifierException("Got a JDOMException while parsing " + + "a response from the DataCite API.", jde, + DOIIdentifierException.BAD_ANSWER); + } + + String handle = null; + + Iterator<Element> it = doc.getDescendants(new ElementFilter("alternateIdentifier")); + while (handle == null && it.hasNext()) + { + Element alternateIdentifier = it.next(); + try + { + handle = HandleManager.resolveUrlToHandle(context, + alternateIdentifier.getText()); + } + catch (SQLException e) + { + throw e; + } + } + + return handle; + } + + protected String extractDOI(Element root) { + Element doi = root.getChild("identifier", root.getNamespace()); + return (null == doi) ? null : doi.getTextTrim(); + } + + protected Element addDOI(String doi, Element root) { + if (null != extractDOI(root)) + { + return root; + } + Element identifier = new Element("identifier", "http://datacite.org/schema/kernel-2.2"); + identifier.setAttribute("identifierType", "DOI"); + identifier.addContent(doi.substring(DOI.SCHEME.length())); + return root.addContent(0, identifier); + } + + protected class DataCiteResponse + { + private final int statusCode; + private final String content; + + protected DataCiteResponse(int statusCode, String content) + { + this.statusCode = statusCode; + this.content = content; + } + + protected int getStatusCode() + { + return this.statusCode; + } + + protected String getContent() + { + return this.content; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..defc49a4eb67cb51634702b4cfccb6087d1bf168 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/doi/package-info.java @@ -0,0 +1,22 @@ +/** + * 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/ + */ +/** + * Make requests to the DOI registration angencies, f.e.to + * <a href='http://n2t.net/ezid/'>EZID</a> DOI service, and analyze the responses. + * + * <p> + * Use {@link org.dspace.identifier.ezid.EZIDRequestFactory#getInstance} to + * configure an {@link org.dspace.identifier.ezid.EZIDRequest} + * with your authority number and credentials. {@code EZIDRequest} encapsulates + * EZID's operations (lookup, create/mint, modify, delete...). + * An operation returns an {@link org.dspace.identifier.ezid.EZIDResponse} which + * gives easy access to EZID's status code and value, status of the underlying + * HTTP request, and key/value pairs found in the response body (if any). + * <p> + */ +package org.dspace.identifier.doi; diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/DateToYear.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/DateToYear.java new file mode 100644 index 0000000000000000000000000000000000000000..ac21379fce5ceec30b74d2c65db4889a080b20f5 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/DateToYear.java @@ -0,0 +1,37 @@ +/** + * 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.identifier.ezid; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Convert a date-time string to the year thereof. + * + * @author mwood + */ +public class DateToYear + implements Transform +{ + private static final SimpleDateFormat parser + = new SimpleDateFormat("yyyy'-'MM'-'dd"); + + @Override + public synchronized String transform(String from) + throws ParseException + { + Date when = parser.parse(from); + Calendar calendar = new GregorianCalendar(); + calendar.setTime(when); + return String.valueOf(calendar.get(Calendar.YEAR)); + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..944734644e28c67b70fa140d4a897654bafd75f1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequest.java @@ -0,0 +1,257 @@ +/** + * 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.identifier.ezid; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.AbstractHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; +import org.dspace.identifier.DOI; +import org.dspace.identifier.IdentifierException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A request to EZID concerning a given (or expected) identifier. + * + * @author Mark H. Wood + */ +public class EZIDRequest +{ + private static final Logger log = LoggerFactory.getLogger(EZIDRequest.class); + + private static final String ID_PATH = "/ezid/id/" + DOI.SCHEME; + + private static final String SHOULDER_PATH = "/ezid/shoulder/" + DOI.SCHEME; + + private static final String UTF_8 = "UTF-8"; + + private static final String MD_KEY_STATUS = "_status"; + + private final AbstractHttpClient client; + + private final String scheme; + + private final String host; + + private final String authority; + + /** + * Prepare a context for requests concerning a specific identifier or + * authority prefix. + * + * @param scheme URL scheme for access to the EZID service. + * @param host Host name for access to the EZID service. + * @param authority DOI authority prefix, e.g. "10.5072/FK2". + * @param username an EZID user identity. + * @param password user's password, or {@code null} for none. + * @throws URISyntaxException if host or authority is bad. + */ + EZIDRequest(String scheme, String host, String authority, String username, String password) + throws URISyntaxException + { + this.scheme = scheme; + + this.host = host; + + if (authority.charAt(authority.length()-1) == '/') + { + this.authority = authority.substring(0, authority.length()-1); + } + else + { + this.authority = authority; + } + + client = new DefaultHttpClient(); + if (null != username) + { + URI uri = new URI(scheme, host, null, null); + client.getCredentialsProvider().setCredentials( + new AuthScope(uri.getHost(), uri.getPort()), + new UsernamePasswordCredentials(username, password)); + } + } + + /** + * Fetch the metadata bound to an identifier. + * + * @throws IdentifierException if the response is error or body malformed. + * @throws IOException if the HTTP request fails. + * @throws URISyntaxException + */ + public EZIDResponse lookup(String name) + throws IdentifierException, IOException, URISyntaxException + { + // GET path + HttpGet request; + URI uri = new URI(scheme, host, ID_PATH + authority + name, null); + log.debug("EZID lookup {}", uri.toASCIIString()); + request = new HttpGet(uri); + HttpResponse response = client.execute(request); + return new EZIDResponse(response); + } + + /** + * Create an identifier with a given name. The name is the end of the + * request path. Note: to "reserve" a given identifier, include "_status = + * reserved" in {@link metadata}. + * + * @param metadata ANVL-encoded key/value pairs. + * @return + */ + public EZIDResponse create(String name, Map<String, String> metadata) + throws IOException, IdentifierException, URISyntaxException + { + // PUT path [+metadata] + HttpPut request; + URI uri = new URI(scheme, host, ID_PATH + authority + '/' + name, null); + log.debug("EZID create {}", uri.toASCIIString()); + request = new HttpPut(uri); + if (null != metadata) + { + try { + request.setEntity(new StringEntity(formatMetadata(metadata), UTF_8)); + } catch (UnsupportedEncodingException ex) { /* SNH */ } + } + HttpResponse response = client.execute(request); + return new EZIDResponse(response); + } + + /** + * Ask EZID to create a unique identifier and return its name. NOTE: to + * "reserve" a unique identifier, include "_status = reserved" in {@link metadata}. + * + * @param metadata ANVL-encoded key/value pairs. + * @return + */ + public EZIDResponse mint(Map<String, String> metadata) + throws IOException, IdentifierException, URISyntaxException + { + // POST path [+metadata] + HttpPost request; + URI uri = new URI(scheme, host, SHOULDER_PATH + authority, null); + log.debug("EZID mint {}", uri.toASCIIString()); + request = new HttpPost(uri); + if (null != metadata) + { + request.setEntity(new StringEntity(formatMetadata(metadata), UTF_8)); + } + HttpResponse response = client.execute(request); + EZIDResponse myResponse = new EZIDResponse(response); + return myResponse; + } + + /** + * Alter the metadata bound to an identifier. + * + * @param metadata fields to be altered. Leave the value of a field's empty + * to delete the field. + * @return + */ + public EZIDResponse modify(String name, Map<String, String> metadata) + throws IOException, IdentifierException, URISyntaxException + { + if (null == metadata) + { + throw new IllegalArgumentException("metadata must not be null"); + } + // POST path +metadata + HttpPost request; + URI uri = new URI(scheme, host, ID_PATH + authority + name, null); + log.debug("EZID modify {}", uri.toASCIIString()); + request = new HttpPost(uri); + request.setEntity(new StringEntity(formatMetadata(metadata), UTF_8)); + HttpResponse response = client.execute(request); + return new EZIDResponse(response); + } + + /** + * Destroy a reserved identifier. Fails if ID was ever public. + */ + public EZIDResponse delete(String name) + throws IOException, IdentifierException, URISyntaxException + { + // DELETE path + HttpDelete request; + URI uri = new URI(scheme, host, ID_PATH + authority + name, null); + log.debug("EZID delete {}", uri.toASCIIString()); + request = new HttpDelete(uri); + HttpResponse response = client.execute(request); + return new EZIDResponse(response); + } + + /** + * Remove a public identifier from view. + */ + public EZIDResponse withdraw(String name) + throws IOException, IdentifierException, URISyntaxException + { + Map<String, String> metadata = new HashMap<String, String>(); + metadata.put(MD_KEY_STATUS, "unavailable"); + return modify(name, metadata); + } + + /** + * Remove a public identifier from view, with a reason. + * + * @param reason annotation for the item's unavailability. + */ + public EZIDResponse withdraw(String name, String reason) + throws IOException, IdentifierException, URISyntaxException + { + Map<String, String> metadata = new HashMap<String, String>(); + metadata.put(MD_KEY_STATUS, "unavailable | " + escape(reason)); + return modify(name, metadata); + } + + /** + * Create ANVL-formatted name/value pairs from a Map. + */ + private static String formatMetadata(Map<String, String> raw) + { + StringBuilder formatted = new StringBuilder(); + for (Entry<String, String> entry : raw.entrySet()) + { + formatted.append(escape(entry.getKey())) + .append(": ") + .append(escape(entry.getValue())) + .append('\n'); + } + + return formatted.toString(); + } + + /** + * Percent-encode a few EZID-specific characters. + * + * @return null for null input. + */ + private static String escape(String s) + { + if (null == s) { return s; } + + return s.replace("%", "%25") + .replace("\n", "%0A") + .replace("\r", "%0D") + .replace(":", "%3A"); + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequestFactory.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7bff29de16583b4dad32ff15812575ddcc6adc46 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDRequestFactory.java @@ -0,0 +1,66 @@ +/** + * 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.identifier.ezid; + +import java.net.URISyntaxException; +import org.springframework.beans.factory.annotation.Required; + +/** + * Create configured EZID requests. + * + * <p>Common EZID constant properties are:</p> + * + * <dl> + * <dt>EZID_SCHEME</dt> + * <dd>URL scheme (e.g. "https")</dd> + * <dt>EZID_HOST</dt> + * <dd>Name of the EZID API host</dd> + * <dt>EZID_PATH</dt> + * <dd>Path to the API endpoints</dd> + * </dl> + * + * @author mwood + */ +public class EZIDRequestFactory +{ + private static String EZID_SCHEME; + private static String EZID_HOST; + + /** + * Configure an EZID request. + * + * @param authority our DOI authority number. + * @param username EZID user name. + * @param password {@code username}'s password. + * @throws URISyntaxException + */ + public EZIDRequest getInstance(String authority, String username, String password) + throws URISyntaxException + { + return new EZIDRequest(EZID_SCHEME, EZID_HOST, authority, username, password); + } + + /** + * @param aEZID_SCHEME the EZID URL scheme to set + */ + @Required + public static void setEZID_SCHEME(String aEZID_SCHEME) + { + EZID_SCHEME = aEZID_SCHEME; + } + + /** + * @param aEZID_HOST the EZID host to set + */ + @Required + public static void setEZID_HOST(String aEZID_HOST) + { + EZID_HOST = aEZID_HOST; + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDResponse.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..1f2af8d523028b2bf79e535405db70c868e21a97 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/EZIDResponse.java @@ -0,0 +1,173 @@ +/** + * 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.identifier.ezid; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.ParseException; +import org.apache.http.util.EntityUtils; +import org.dspace.identifier.IdentifierException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Decoded response data evoked by a request made to EZID. + */ +public class EZIDResponse +{ + private static final Logger log = LoggerFactory.getLogger(EZIDResponse.class); + + private static final String UTF_8 = "UTF-8"; + + private final String status; + + private final String statusValue; + + private final Map<String, String> attributes = new HashMap<String, String>(); + + private final HttpResponse response; + + public EZIDResponse(HttpResponse response) + throws IdentifierException + { + this.response = response; + + HttpEntity responseBody = response.getEntity(); + + // Collect the content of the percent-encoded response. + String body; + try + { + body = EntityUtils.toString(responseBody, UTF_8); + } catch (IOException ex) + { + log.error(ex.getMessage()); + throw new IdentifierException("EZID response not understood: " + + ex.getMessage()); + } catch (ParseException ex) + { + log.error(ex.getMessage()); + throw new IdentifierException("EZID response not understood: " + + ex.getMessage()); + } + + String[] parts; + + String[] lines = body.split("[\\n\\r]"); + + // First line is request status and message or value + parts = lines[0].split(":", 2); + status = parts[0].trim(); + if (parts.length > 1) + { + statusValue = parts[1].trim(); + } + else + { + statusValue = null; + } + + // Remaining lines are key: value pairs + for (int i = 1; i < lines.length; i++) + { + parts = lines[i].split(":", 2); + String key = null, value = null; + try { + key = URLDecoder.decode(parts[0], UTF_8).trim(); + if (parts.length > 1) + { + value = URLDecoder.decode(parts[1], UTF_8).trim(); + } + else + { + value = null; + } + } catch (UnsupportedEncodingException e) { + // XXX SNH, we always use UTF-8 which is required by the Java spec. + } + attributes.put(key, value); + } + } + + /** + * Did the EZID request succeed? + * + * @return returned status was success. + */ + public boolean isSuccess() + { + return status.equalsIgnoreCase("success"); + } + + /** + * Get the EZID request status. + * + * @return should be "success" or "error". + */ + public String getEZIDStatus() + { + return status; + } + + /** + * Value associated with the EZID status (identifier, error text, etc.). + */ + public String getEZIDStatusValue() + { + return statusValue; + } + + /** + * Expose the available keys. + * + * @return all keys found in the response. + */ + public List<String> getKeys() + { + List<String> keys = new ArrayList<String>(); + for (String key : attributes.keySet()) + { + keys.add(key); + } + return keys; + } + + /** + * Look up the value of a given response datum. + * + * @param key the datum to look up. + * @return the value of {@code key}, or null if {@code key} is undefined. + */ + public String get(String key) + { + return attributes.get(key); + } + + /** + * @return status of the HTTP request. + */ + public int getHttpStatusCode() + { + return response.getStatusLine().getStatusCode(); + } + + /** + * @return reason for status of the HTTP request. + */ + public String getHttpReasonPhrase() + { + return response.getStatusLine().getReasonPhrase(); + } +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/ezid/Transform.java b/dspace-api/src/main/java/org/dspace/identifier/ezid/Transform.java new file mode 100644 index 0000000000000000000000000000000000000000..f57aee0e48a4cbc3072c472390e571f7ac748c05 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/ezid/Transform.java @@ -0,0 +1,23 @@ +/** + * 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.identifier.ezid; + +/** + * Convert metadata strings to other forms. + * + * @author mwood + */ +public interface Transform +{ + /** + * Convert the input form to the desired output form. + */ + public String transform(String from) + throws Exception; +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/package-info.java b/dspace-api/src/main/java/org/dspace/identifier/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..95f24195173bca1eea8763e07efd67b969ac95d1 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/identifier/package-info.java @@ -0,0 +1,17 @@ +/** + * 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/ + */ +/** + * Providers of durable unique identifiers (Handles, DOIs, etc.). + * Generally, subclasses of {@link org.dspace.identifier.IdentifierProvider} + * offer methods to create, delete, and resolve subclasses of + * {@link org.dspace.identifier.Identifier}. Classes outside this package + * should rely on {@link org.dspace.identifier.IdentifierService} to perform + * these operations using the most appropriate provider. + */ + +package org.dspace.identifier; 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/statistics/util/package-info.java b/dspace-api/src/main/java/org/dspace/statistics/util/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..ecb1b22615415612a9511a41d569975cd2363c3f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/statistics/util/package-info.java @@ -0,0 +1,15 @@ +/** + * 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/ + */ +/** + * Mostly classes for dealing with detection of spiders, and command line tools. + * <p> + * One can find a database of User-Agent strings classified as clients, bots, + * etc. at <a href='http://www.user-agents.org/'>www.user-agents.org</a>. + */ + +package org.dspace.statistics.util; diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivFileDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivFileDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..04949439f9fa687db564cfc841d2e811549c5266 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivFileDataLoader.java @@ -0,0 +1,174 @@ +/** + * 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.submit.lookup; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bte.exceptions.MalformedSourceException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + * + */ +public class ArXivFileDataLoader extends FileDataLoader +{ + + private static Logger log = Logger.getLogger(ArXivFileDataLoader.class); + + Map<String, String> fieldMap; // mapping between service fields and local + // intermediate fields + + /** + * Empty constructor + */ + public ArXivFileDataLoader() + { + } + + /** + * @param filename + */ + public ArXivFileDataLoader(String filename) + { + super(filename); + } + + /* + * (non-Javadoc) + * + * @see gr.ekt.bte.core.DataLoader#getRecords() + */ + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + try + { + InputStream inputStream = new FileInputStream(new File(filename)); + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(inputStream); + + Element xmlRoot = inDoc.getDocumentElement(); + List<Element> dataRoots = XMLUtils.getElementList(xmlRoot, "entry"); + + for (Element dataRoot : dataRoots) + { + Record record = ArxivUtils.convertArxixDomToRecord(dataRoot); + if (record != null) + { + recordSet.addRecord(convertFields(record)); + } + } + } + catch (FileNotFoundException e) + { + log.error(e.getMessage(), e); + } + catch (ParserConfigurationException e) + { + log.error(e.getMessage(), e); + } + catch (SAXException e) + { + log.error(e.getMessage(), e); + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + + return recordSet; + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec) + */ + @Override + public RecordSet getRecords(DataLoadingSpec spec) + throws MalformedSourceException + { + if (spec.getOffset() > 0) + { + return new RecordSet(); + } + return getRecords(); + } + + public Record convertFields(Record publication) + { + for (String fieldName : fieldMap.keySet()) + { + String md = null; + if (fieldMap != null) + { + md = this.fieldMap.get(fieldName); + } + + if (StringUtils.isBlank(md)) + { + continue; + } + else + { + md = md.trim(); + } + + if (publication.isMutable()) + { + List<Value> values = publication.getValues(fieldName); + publication.makeMutable().removeField(fieldName); + publication.makeMutable().addField(md, values); + } + } + + return publication; + } + + public void setFieldMap(Map<String, String> fieldMap) + { + this.fieldMap = fieldMap; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivOnlineDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivOnlineDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..0bb94f1a329c7cc0c32be054dc0c443e62ffa213 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivOnlineDataLoader.java @@ -0,0 +1,98 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpException; +import org.dspace.core.Context; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class ArXivOnlineDataLoader extends NetworkSubmissionLookupDataLoader +{ + private ArXivService arXivService = new ArXivService(); + + private boolean searchProvider = true; + + public void setArXivService(ArXivService arXivService) + { + this.arXivService = arXivService; + } + + @Override + public List<String> getSupportedIdentifiers() + { + return Arrays.asList(new String[] { ARXIV, DOI }); + } + + public void setSearchProvider(boolean searchProvider) + { + this.searchProvider = searchProvider; + } + + @Override + public boolean isSearchProvider() + { + return searchProvider; + } + + @Override + public List<Record> getByIdentifier(Context context, + Map<String, Set<String>> keys) throws HttpException, IOException + { + List<Record> results = new ArrayList<Record>(); + if (keys != null) + { + Set<String> dois = keys.get(DOI); + Set<String> arxivids = keys.get(ARXIV); + List<Record> items = new ArrayList<Record>(); + if (dois != null && dois.size() > 0) + { + items.addAll(arXivService.getByDOIs(dois)); + } + if (arxivids != null && arxivids.size() > 0) + { + for (String arxivid : arxivids) + { + items.add(arXivService.getByArXivIDs(arxivid)); + } + } + + for (Record item : items) + { + results.add(convertFields(item)); + } + } + return results; + } + + @Override + public List<Record> search(Context context, String title, String author, + int year) throws HttpException, IOException + { + List<Record> results = new ArrayList<Record>(); + List<Record> items = arXivService.searchByTerm(title, author, year); + for (Record item : items) + { + results.add(convertFields(item)); + } + return results; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivService.java b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivService.java new file mode 100644 index 0000000000000000000000000000000000000000..42e3b1de081ede8cc75392929a56c0db0d09efe0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/ArXivService.java @@ -0,0 +1,170 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.dspace.core.ConfigurationManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class ArXivService +{ + private int timeout = 1000; + + public void setTimeout(int timeout) + { + this.timeout = timeout; + } + + public List<Record> getByDOIs(Set<String> dois) throws HttpException, + IOException + { + if (dois != null && dois.size() > 0) + { + String doisQuery = StringUtils.join(dois.iterator(), " OR "); + return search(doisQuery, null, 100); + } + return null; + } + + public List<Record> searchByTerm(String title, String author, int year) + throws HttpException, IOException + { + StringBuffer query = new StringBuffer(); + if (StringUtils.isNotBlank(title)) + { + query.append("ti:\"").append(title).append("\""); + } + if (StringUtils.isNotBlank(author)) + { + // [FAU] + if (query.length() > 0) + query.append(" AND "); + query.append("au:\"").append(author).append("\""); + } + return search(query.toString(), "", 10); + } + + private List<Record> search(String query, String arxivid, int max_result) + throws IOException, HttpException + { + List<Record> results = new ArrayList<Record>(); + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + client.setTimeout(timeout); + method = new GetMethod("http://export.arxiv.org/api/query"); + NameValuePair id = new NameValuePair("id_list", arxivid); + NameValuePair queryParam = new NameValuePair("search_query", + query); + NameValuePair count = new NameValuePair("max_results", + String.valueOf(max_result)); + method.setQueryString(new NameValuePair[] { id, queryParam, + count }); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + if (statusCode == HttpStatus.SC_BAD_REQUEST) + throw new RuntimeException("arXiv query is not valid"); + else + throw new RuntimeException("Http call failed: " + + method.getStatusLine()); + } + + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(method.getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + List<Element> dataRoots = XMLUtils.getElementList(xmlRoot, + "entry"); + + for (Element dataRoot : dataRoots) + { + Record crossitem = ArxivUtils + .convertArxixDomToRecord(dataRoot); + if (crossitem != null) + { + results.add(crossitem); + } + } + } + catch (Exception e) + { + throw new RuntimeException( + "ArXiv identifier is not valid or not exist"); + } + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + + return results; + } + + public Record getByArXivIDs(String raw) throws HttpException, IOException + { + if (StringUtils.isNotBlank(raw)) + { + raw = raw.trim(); + if (raw.startsWith("http://arxiv.org/abs/")) + { + raw = raw.substring("http://arxiv.org/abs/".length()); + } + else if (raw.toLowerCase().startsWith("arxiv:")) + { + raw = raw.substring("arxiv:".length()); + } + List<Record> result = search("", raw, 1); + if (result != null && result.size() > 0) + { + return result.get(0); + } + } + return null; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/ArxivUtils.java b/dspace-api/src/main/java/org/dspace/submit/lookup/ArxivUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..c7db15e302973fe71886247e86e30ee12dbc6018 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/ArxivUtils.java @@ -0,0 +1,160 @@ +/** + * 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.submit.lookup; + +import java.util.LinkedList; +import java.util.List; + +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import org.dspace.app.util.XMLUtils; +import org.dspace.submit.util.SubmissionLookupPublication; +import org.w3c.dom.Element; + +/** + * + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + * + */ +public class ArxivUtils +{ + + public static Record convertArxixDomToRecord(Element dataRoot) + { + MutableRecord record = new SubmissionLookupPublication(""); + + String articleTitle = XMLUtils.getElementValue(dataRoot, "title"); + if (articleTitle != null) + record.addValue("title", new StringValue(articleTitle)); + String summary = XMLUtils.getElementValue(dataRoot, "summary"); + if (summary != null) + record.addValue("summary", new StringValue(summary)); + String year = XMLUtils.getElementValue(dataRoot, "published"); + if (year != null) + record.addValue("published", new StringValue(year)); + String splashPageUrl = XMLUtils.getElementValue(dataRoot, "id"); + if (splashPageUrl != null) + record.addValue("id", new StringValue(splashPageUrl)); + String comment = XMLUtils.getElementValue(dataRoot, "arxiv:comment"); + if (comment != null) + record.addValue("comment", new StringValue(comment)); + + List<Element> links = XMLUtils.getElementList(dataRoot, "link"); + if (links != null) + { + for (Element link : links) + { + if ("related".equals(link.getAttribute("rel")) + && "pdf".equals(link.getAttribute("title"))) + { + String pdfUrl = link.getAttribute("href"); + if (pdfUrl != null) + record.addValue("pdfUrl", new StringValue(pdfUrl)); + } + } + } + + String doi = XMLUtils.getElementValue(dataRoot, "arxiv:doi"); + if (doi != null) + record.addValue("doi", new StringValue(doi)); + String journalRef = XMLUtils.getElementValue(dataRoot, + "arxiv:journal_ref"); + if (journalRef != null) + record.addValue("journalRef", new StringValue(journalRef)); + + List<String> primaryCategory = new LinkedList<String>(); + List<Element> primaryCategoryList = XMLUtils.getElementList(dataRoot, + "arxiv:primary_category"); + if (primaryCategoryList != null) + { + for (Element primaryCategoryElement : primaryCategoryList) + { + primaryCategory + .add(primaryCategoryElement.getAttribute("term")); + } + } + + if (primaryCategory.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : primaryCategory) + { + values.add(new StringValue(s)); + } + record.addField("primaryCategory", values); + } + + List<String> category = new LinkedList<String>(); + List<Element> categoryList = XMLUtils.getElementList(dataRoot, + "category"); + if (categoryList != null) + { + for (Element categoryElement : categoryList) + { + category.add(categoryElement.getAttribute("term")); + } + } + + if (category.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : category) + { + values.add(new StringValue(s)); + } + record.addField("category", values); + } + + List<String> authors = new LinkedList<String>(); + List<String> authorsWithAffiliations = new LinkedList<String>(); + List<Element> authorList = XMLUtils.getElementList(dataRoot, "author"); + if (authorList != null) + { + for (Element authorElement : authorList) + { + String authorName = XMLUtils.getElementValue(authorElement, "name"); + String authorAffiliation = XMLUtils.getElementValue(authorElement, "arxiv:affiliation"); + + authors.add(authorName); + authorsWithAffiliations.add(authorName +": " + authorAffiliation); + } + } + + if (authors.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String sArray : authors) + { + values.add(new StringValue(sArray)); + } + record.addField("author", values); + } + + if (authorsWithAffiliations.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String sArray : authorsWithAffiliations) + { + values.add(new StringValue(sArray)); + } + record.addField("authorWithAffiliation", values); + } + + return record; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiFileDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiFileDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..18f092b13fad96076a2854bdc4e68d547185b8b4 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiFileDataLoader.java @@ -0,0 +1,172 @@ +/** + * 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.submit.lookup; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bte.exceptions.MalformedSourceException; + +/** + * Load metadata from CiNii formated file + * + * @author Keiji Suzuki + * + */ +public class CiNiiFileDataLoader extends FileDataLoader +{ + + private static Logger log = Logger.getLogger(CiNiiFileDataLoader.class); + + Map<String, String> fieldMap; // mapping between service fields and local + // intermediate fields + + /** + * Empty constructor + */ + public CiNiiFileDataLoader() + { + } + + /** + * @param filename + */ + public CiNiiFileDataLoader(String filename) + { + super(filename); + } + + /* + * (non-Javadoc) + * + * @see gr.ekt.bte.core.DataLoader#getRecords() + */ + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + try + { + InputStream inputStream = new FileInputStream(new File(filename)); + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(inputStream); + + Element xmlRoot = inDoc.getDocumentElement(); + + // There is no element to represent an record, so we can not process + // multi records at once. + Record record = CiNiiUtils.convertCiNiiDomToRecord(xmlRoot); + if (record != null) + { + recordSet.addRecord(convertFields(record)); + } + } + catch (FileNotFoundException e) + { + log.error(e.getMessage(), e); + } + catch (ParserConfigurationException e) + { + log.error(e.getMessage(), e); + } + catch (SAXException e) + { + log.error(e.getMessage(), e); + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + + return recordSet; + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec) + */ + @Override + public RecordSet getRecords(DataLoadingSpec spec) + throws MalformedSourceException + { + if (spec.getOffset() > 0) + { + return new RecordSet(); + } + + return getRecords(); + } + + public Record convertFields(Record publication) + { + for (String fieldName : fieldMap.keySet()) + { + String md = null; + if (fieldMap != null) + { + md = this.fieldMap.get(fieldName); + } + + if (StringUtils.isBlank(md)) + { + continue; + } + else + { + md = md.trim(); + } + + if (publication.isMutable()) + { + List<Value> values = publication.getValues(fieldName); + publication.makeMutable().removeField(fieldName); + publication.makeMutable().addField(md, values); + } + } + + return publication; + } + + public void setFieldMap(Map<String, String> fieldMap) + { + this.fieldMap = fieldMap; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiOnlineDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiOnlineDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..db831c751cf77135a29d5e5680a8f08586d280e0 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiOnlineDataLoader.java @@ -0,0 +1,120 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpException; +import org.dspace.core.Context; + +/** + * Load metadata from CiNii RDF API + * @author Keiji Suzuki + */ +public class CiNiiOnlineDataLoader extends NetworkSubmissionLookupDataLoader +{ + private CiNiiService ciniiService = new CiNiiService(); + + private boolean searchProvider = true; + + /** Application id to use CiNii */ + private String appId = null; + + /** max result number to return */ + private int maxResults = 10; + + public void setCiNiiService(CiNiiService ciniiService) + { + this.ciniiService = ciniiService; + } + + @Override + public List<String> getSupportedIdentifiers() + { + return Arrays.asList(new String[] { CINII }); + } + + public void setSearchProvider(boolean searchProvider) + { + this.searchProvider = searchProvider; + } + + @Override + public boolean isSearchProvider() + { + return searchProvider; + } + + @Override + public List<Record> getByIdentifier(Context context, + Map<String, Set<String>> keys) throws HttpException, IOException + { + if (appId == null) + { + throw new RuntimeException("No CiNii Application ID is specified!"); + } + + List<Record> results = new ArrayList<Record>(); + if (keys != null) + { + Set<String> ciniiids = keys.get(CINII); + if (ciniiids != null && ciniiids.size() > 0) + { + for (String ciniiid : ciniiids) + { + Record record = ciniiService.getByCiNiiID(ciniiid, getAppId()); + if (record != null) + { + results.add(convertFields(record)); + } + } + } + } + return results; + } + + @Override + public List<Record> search(Context context, String title, String author, int year) + throws HttpException, IOException + { + if (appId == null) + { + throw new RuntimeException("No CiNii Application ID is specified!"); + } + + return ciniiService.searchByTerm(title, author, year, + getMaxResults(), getAppId()); + } + + public String getAppId() + { + return appId; + } + + public void setAppId(String appId) + { + this.appId = appId; + } + + public int getMaxResults() + { + return maxResults; + } + + public void setMaxResults(int maxResults) + { + this.maxResults = maxResults; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiService.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiService.java new file mode 100644 index 0000000000000000000000000000000000000000..e2092c8c49363841b14e314675c713c997c78b2f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiService.java @@ -0,0 +1,221 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * @author Keiji Suzuki + */ +public class CiNiiService +{ + /** log4j category */ + private static Logger log = Logger.getLogger(CiNiiService.class); + + private int timeout = 1000; + + public void setTimeout(int timeout) + { + this.timeout = timeout; + } + + public Record getByCiNiiID(String id, String appId) throws HttpException, + IOException + { + return search(id, appId); + } + + public List<Record> searchByTerm(String title, String author, int year, + int maxResults, String appId) + throws HttpException, IOException + { + List<Record> records = new ArrayList<Record>(); + + List<String> ids = getCiNiiIDs(title, author, year, maxResults, appId); + if (ids != null && ids.size() > 0) + { + for (String id : ids) + { + Record record = search(id, appId); + if (record != null) + { + records.add(record); + } + } + } + + return records; + } + + /** + * Get metadata by searching CiNii RDF API with CiNii NAID + * + */ + private Record search(String id, String appId) + throws IOException, HttpException + { + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + client.setTimeout(timeout); + method = new GetMethod("http://ci.nii.ac.jp/naid/"+id+".rdf?appid="+appId); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + if (statusCode == HttpStatus.SC_BAD_REQUEST) + throw new RuntimeException("CiNii RDF is not valid"); + else + throw new RuntimeException("CiNii RDF Http call failed: " + + method.getStatusLine()); + } + + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(method.getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + + return CiNiiUtils.convertCiNiiDomToRecord(xmlRoot); + } + catch (Exception e) + { + throw new RuntimeException( + "CiNii RDF identifier is not valid or not exist"); + } + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } + + /** + * Get CiNii NAIDs by searching CiNii OpenURL API with title, author and year + * + */ + private List<String> getCiNiiIDs(String title, String author, int year, + int maxResults, String appId) + throws IOException, HttpException + { + // Need at least one query term + if (title == null && author == null && year == -1) + { + return null; + } + + GetMethod method = null; + List<String> ids = new ArrayList<String>(); + try + { + HttpClient client = new HttpClient(); + client.setTimeout(timeout); + StringBuilder query = new StringBuilder(); + query.append("format=rss&appid=").append(appId) + .append("&count=").append(maxResults); + if (title != null) + { + query.append("&title=").append(URLEncoder.encode(title, "UTF-8")); + } + if (author != null) + { + query.append("&author=").append(URLEncoder.encode(author, "UTF-8")); + } + if (year != -1) + { + query.append("&year_from=").append(String.valueOf(year)); + query.append("&year_to=").append(String.valueOf(year)); + } + method = new GetMethod("http://ci.nii.ac.jp/opensearch/search?"+query.toString()); + // Execute the method. + int statusCode = client.executeMethod(method); + if (statusCode != HttpStatus.SC_OK) + { + if (statusCode == HttpStatus.SC_BAD_REQUEST) + throw new RuntimeException("CiNii OpenSearch query is not valid"); + else + throw new RuntimeException("CiNii OpenSearch call failed: " + + method.getStatusLine()); + } + + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(method.getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + List<Element> items = XMLUtils.getElementList(xmlRoot, "item"); + + int url_len = "http://ci.nii.ac.jp/naid/".length(); + for (Element item : items) + { + String about = item.getAttribute("rdf:about"); + if (about.length() > url_len) + { + ids.add(about.substring(url_len)); + } + } + + return ids; + } + catch (Exception e) + { + throw new RuntimeException( + "CiNii OpenSearch results is not valid or not exist"); + } + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiUtils.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e134257e59da75d6b624d31877a543cfc6e8f50a --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CiNiiUtils.java @@ -0,0 +1,268 @@ +/** + * 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.submit.lookup; + +import java.util.LinkedList; +import java.util.List; + +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.dspace.submit.util.SubmissionLookupPublication; +import org.w3c.dom.Element; + +/** + * + * @author Keiji Suzuki + * + */ +public class CiNiiUtils +{ + public static Record convertCiNiiDomToRecord(Element xmlRoot) + { + MutableRecord record = new SubmissionLookupPublication(""); + + List<Element> list = XMLUtils.getElementList(xmlRoot, "rdf:Description"); + // Valid CiNii record should have three rdf:Description elements + if (list.size() < 3) + { + return record; + } + + Element description_ja = list.get(0); // Japanese description + Element description_en = list.get(1); // English description + // Element description3 = list.get(2); // Authors information: NOT USE here + + String language = XMLUtils.getElementValue(description_ja, "dc:language"); + language = language != null ? language.toLowerCase() : "ja"; + record.addValue("language", new StringValue(language)); + + if ("ja".equals(language) || "jpn".equals(language)) + { + String title = XMLUtils.getElementValue(description_ja, "dc:title"); + if (title != null) + { + record.addValue("title", new StringValue(title)); + } + String titleAlternative = XMLUtils.getElementValue(description_en, "dc:title"); + if (titleAlternative != null) + { + record.addValue("titleAlternative", new StringValue(titleAlternative)); + } + + List<Value> authors = getAuthors(description_ja); + if (authors.size() > 0) + { + record.addField("authors", authors); + } + List<Value> authorAlternative = getAuthors(description_en); + if (authorAlternative.size() > 0) + { + record.addField("auhtorAlternative", authorAlternative); + } + + String publisher = XMLUtils.getElementValue(description_ja, "dc:publisher"); + if (publisher != null) + { + record.addValue("publisher", new StringValue(publisher)); + } + } + else + { + String title = XMLUtils.getElementValue(description_en, "dc:title"); + if (title != null) + { + record.addValue("title", new StringValue(title)); + } + String titleAlternative = XMLUtils.getElementValue(description_ja, "dc:title"); + if (titleAlternative != null) + { + record.addValue("titleAlternative", new StringValue(titleAlternative)); + } + + List<Value> authors = getAuthors(description_en); + if (authors.size() > 0) + { + record.addField("authors", authors); + } + List<Value> authorAlternative = getAuthors(description_ja); + if (authorAlternative.size() > 0) + { + record.addField("authorAlternative", authorAlternative); + } + + String publisher = XMLUtils.getElementValue(description_en, "dc:publisher"); + if (publisher != null) + { + record.addValue("publisher", new StringValue(publisher)); + } + } + + String abstract_ja = XMLUtils.getElementValue(description_ja, "dc:description"); + String abstract_en = XMLUtils.getElementValue(description_en, "dc:description"); + if (abstract_ja != null && abstract_en != null) + { + List<Value> description = new LinkedList<Value>(); + description.add(new StringValue(abstract_ja)); + description.add(new StringValue(abstract_en)); + record.addField("description", description); + } + else if (abstract_ja != null) + { + record.addValue("description", new StringValue(abstract_ja)); + } + else if (abstract_en != null) + { + record.addValue("description", new StringValue(abstract_en)); + } + + List<Value> subjects = getSubjects(description_ja); + subjects.addAll(getSubjects(description_en)); + if (subjects.size() > 0) + { + record.addField("subjects", subjects); + } + + String journal_j = XMLUtils.getElementValue(description_ja, "prism:publicationName"); + String journal_e = XMLUtils.getElementValue(description_en, "prism:publicationName"); + if (journal_j != null && journal_e != null) + { + record.addValue("journal", new StringValue(journal_j+" = "+journal_e)); + } + else if (journal_j != null) + { + + record.addValue("journal", new StringValue(journal_j)); + } + else if (journal_e != null) + { + + record.addValue("journal", new StringValue(journal_e)); + } + + String volume = XMLUtils.getElementValue(description_ja, "prism:volume"); + if (volume != null) + { + record.addValue("volume", new StringValue(volume)); + } + + String issue = XMLUtils.getElementValue(description_ja, "prism:number"); + if (issue != null) + { + record.addValue("issue", new StringValue(issue)); + } + + String spage = XMLUtils.getElementValue(description_ja, "prism:startingPage"); + if (spage != null) + { + record.addValue("spage", new StringValue(spage)); + } + + String epage = XMLUtils.getElementValue(description_ja, "prism:endingPage"); + if (epage != null) + { + record.addValue("epage", new StringValue(epage)); + } + + String pages = XMLUtils.getElementValue(description_ja, "prism:pageRange"); + if (pages != null && spage == null) + { + int pos = pages.indexOf("-"); + if (pos > -1) + { + spage = pages.substring(0, pos); + epage = pages.substring(pos+1, pages.length() - pos); + if (!epage.equals("") && spage.length() > epage.length()) + { + epage = spage.substring(0, spage.length() - epage.length()) + epage; + } + } + else + { + spage = pages; + epage = ""; + } + record.addValue("spage", new StringValue(spage)); + if (!epage.equals("") && epage == null) + { + record.addValue("epage", new StringValue(epage)); + } + } + + String issn = XMLUtils.getElementValue(description_ja, "prism:issn"); + if (issn != null) + { + record.addValue("issn", new StringValue(issn)); + } + + String issued = XMLUtils.getElementValue(description_ja, "prism:publicationDate"); + if (issued != null) + { + record.addValue("issued", new StringValue(issued)); + } + + String ncid = XMLUtils.getElementValue(description_ja, "cinii:ncid"); + if (ncid != null) + { + record.addValue("ncid", new StringValue(ncid)); + } + + String naid = XMLUtils.getElementValue(description_ja, "cinii:naid"); + if (naid != null) + { + record.addValue("naid", new StringValue(naid)); + } + + return record; + } + + private static List<Value> getAuthors(Element element) + { + List<Value> authors = new LinkedList<Value>(); + + List<String> authorList = XMLUtils.getElementValueList(element, "dc:creator"); + if (authorList != null && authorList.size() > 0) + { + for (String author : authorList) + { + int pos = author.indexOf(" "); + if (pos > -1) + author = author.substring(0, pos) + "," + author.substring(pos); + authors.add(new StringValue(author)); + } + } + + return authors; + } + + private static List<Value> getSubjects(Element element) + { + List<Value> subjects = new LinkedList<Value>(); + + List<Element> topicList = XMLUtils.getElementList(element, "foaf:topic"); + String attrValue = null; + for (Element topic : topicList) + { + attrValue = topic.getAttribute("dc:title"); + if (StringUtils.isNotBlank(attrValue)) + { + subjects.add(new StringValue(attrValue.trim())); + } + } + + return subjects; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefFileDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefFileDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..e56177711735307b1abf97cbea0b3a30b7173798 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefFileDataLoader.java @@ -0,0 +1,167 @@ +/** + * 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.submit.lookup; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bte.exceptions.MalformedSourceException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class CrossRefFileDataLoader extends FileDataLoader +{ + + Map<String, String> fieldMap; // mapping between service fields and local + // intermediate fields + + /** + * + */ + public CrossRefFileDataLoader() + { + } + + /** + * @param filename + */ + public CrossRefFileDataLoader(String filename) + { + super(filename); + } + + /* + * (non-Javadoc) + * + * @see gr.ekt.bte.core.DataLoader#getRecords() + */ + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + try + { + InputStream inputStream = new FileInputStream(new File(filename)); + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory.newDocumentBuilder(); + Document inDoc = db.parse(inputStream); + + Element xmlRoot = inDoc.getDocumentElement(); + Element queryResult = XMLUtils.getSingleElement(xmlRoot, "query_result"); + Element body = XMLUtils.getSingleElement(queryResult, "body"); + Element dataRoot = XMLUtils.getSingleElement(body, "query"); + Record record = CrossRefUtils.convertCrossRefDomToRecord(dataRoot); + recordSet.addRecord(convertFields(record)); + + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + catch (ParserConfigurationException e) + { + e.printStackTrace(); + } + catch (SAXException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return recordSet; + + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec) + */ + @Override + public RecordSet getRecords(DataLoadingSpec spec) + throws MalformedSourceException + { + if (spec.getOffset() > 0) + { + return new RecordSet(); + } + return getRecords(); + } + + public Record convertFields(Record publication) + { + for (String fieldName : fieldMap.keySet()) + { + String md = null; + if (fieldMap != null) + { + md = this.fieldMap.get(fieldName); + } + + if (StringUtils.isBlank(md)) + { + continue; + } + else + { + md = md.trim(); + } + + if (publication.isMutable()) + { + List<Value> values = publication.getValues(fieldName); + publication.makeMutable().removeField(fieldName); + publication.makeMutable().addField(md, values); + } + } + + return publication; + } + + public void setFieldMap(Map<String, String> fieldMap) + { + this.fieldMap = fieldMap; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefOnlineDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefOnlineDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..ec86ac45ec0a8e61cbd3c99e4b1b523102758935 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefOnlineDataLoader.java @@ -0,0 +1,130 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.httpclient.HttpException; +import org.dspace.core.Context; +import org.jdom.JDOMException; +import org.xml.sax.SAXException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class CrossRefOnlineDataLoader extends NetworkSubmissionLookupDataLoader +{ + private CrossRefService crossrefService = new CrossRefService(); + + private boolean searchProvider = true; + + private String apiKey = null; + private int maxResults = 10; + + public void setSearchProvider(boolean searchProvider) + { + this.searchProvider = searchProvider; + } + + public void setCrossrefService(CrossRefService crossrefService) + { + this.crossrefService = crossrefService; + } + + @Override + public List<String> getSupportedIdentifiers() + { + return Arrays.asList(new String[] { DOI }); + } + + @Override + public List<Record> getByIdentifier(Context context, + Map<String, Set<String>> keys) throws HttpException, IOException + { + if (keys != null && keys.containsKey(DOI)) + { + Set<String> dois = keys.get(DOI); + List<Record> items = null; + List<Record> results = new ArrayList<Record>(); + + if (getApiKey() == null){ + throw new RuntimeException("No CrossRef API key is specified!"); + } + + try + { + items = crossrefService.search(context, dois, getApiKey()); + } + catch (JDOMException e) + { + throw new RuntimeException(e.getMessage(), e); + } + catch (ParserConfigurationException e) + { + throw new RuntimeException(e.getMessage(), e); + } + catch (SAXException e) + { + throw new RuntimeException(e.getMessage(), e); + } + for (Record record : items) + { + results.add(convertFields(record)); + } + return results; + } + return null; + } + + @Override + public List<Record> search(Context context, String title, String author, + int year) throws HttpException, IOException + { + if (getApiKey() == null){ + throw new RuntimeException("No CrossRef API key is specified!"); + } + + List<Record> items = crossrefService.search(context, title, author, + year, getMaxResults(), getApiKey()); + return items; + } + + @Override + public boolean isSearchProvider() + { + return searchProvider; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public int getMaxResults() { + return maxResults; + } + + public void setMaxResults(int maxResults) { + this.maxResults = maxResults; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefService.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefService.java new file mode 100644 index 0000000000000000000000000000000000000000..32a5fa19ce039b748e16d1f21d776d6850be876b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefService.java @@ -0,0 +1,219 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.XMLUtils; +import org.dspace.core.Context; +import org.dspace.core.LogManager; +import org.jdom.JDOMException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class CrossRefService +{ + + private static final Logger log = Logger.getLogger(CrossRefService.class); + + private int timeout = 1000; + + public void setTimeout(int timeout) + { + this.timeout = timeout; + } + + public List<Record> search(Context context, Set<String> dois, String apiKey) + throws HttpException, IOException, JDOMException, + ParserConfigurationException, SAXException + { + List<Record> results = new ArrayList<Record>(); + if (dois != null && dois.size() > 0) + { + for (String record : dois) + { + try + { + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + client.setConnectionTimeout(timeout); + method = new GetMethod( + "http://www.crossref.org/openurl/"); + + NameValuePair pid = new NameValuePair("pid", apiKey); + NameValuePair noredirect = new NameValuePair( + "noredirect", "true"); + NameValuePair id = new NameValuePair("id", record); + method.setQueryString(new NameValuePair[] { pid, + noredirect, id }); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + throw new RuntimeException("Http call failed: " + + method.getStatusLine()); + } + + Record crossitem; + try + { + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder db = factory + .newDocumentBuilder(); + Document inDoc = db.parse(method + .getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + Element queryResult = XMLUtils.getSingleElement(xmlRoot, "query_result"); + Element body = XMLUtils.getSingleElement(queryResult, "body"); + Element dataRoot = XMLUtils.getSingleElement(body, "query"); + + crossitem = CrossRefUtils + .convertCrossRefDomToRecord(dataRoot); + results.add(crossitem); + } + catch (Exception e) + { + log.warn(LogManager + .getHeader( + context, + "retrieveRecordDOI", + record + + " DOI is not valid or not exist: " + + e.getMessage())); + } + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } + catch (RuntimeException rt) + { + log.error(rt.getMessage(), rt); + } + } + } + return results; + } + + public NameValuePair[] buildQueryPart(String title, String author, + int year, int count) + { + StringBuffer sb = new StringBuffer(); + if (StringUtils.isNotBlank(title)) + { + sb.append(title); + } + sb.append(" "); + if (StringUtils.isNotBlank(author)) + { + sb.append(author); + } + String q = sb.toString().trim(); + NameValuePair qParam = new NameValuePair("q", title); + NameValuePair yearParam = new NameValuePair("year", + year != -1 ? String.valueOf(year) : ""); + NameValuePair countParam = new NameValuePair("rows", + count != -1 ? String.valueOf(count) : ""); + + NameValuePair[] query = new NameValuePair[] { qParam, yearParam, + countParam }; + return query; + } + + public List<Record> search(Context context, String title, String authors, + int year, int count, String apiKey) throws IOException, HttpException + { + GetMethod method = null; + try + { + NameValuePair[] query = buildQueryPart(title, authors, year, count); + HttpClient client = new HttpClient(); + client.setTimeout(timeout); + method = new GetMethod("http://search.labs.crossref.org/dois"); + + method.setQueryString(query); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + throw new RuntimeException("Http call failed:: " + + method.getStatusLine()); + } + + Gson gson = new Gson(); + Type listType = new TypeToken<ArrayList<Map>>() + { + }.getType(); + List<Map> json = gson.fromJson(method.getResponseBodyAsString(), + listType); + Set<String> dois = new HashSet<String>(); + for (Map r : json) + { + dois.add(SubmissionLookupUtils.normalizeDOI((String) r + .get("doi"))); + } + method.releaseConnection(); + + return search(context, dois, apiKey); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefUtils.java b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..e05d6d4577ef74bdc0347f5cd35f89e5d76c4b6d --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/CrossRefUtils.java @@ -0,0 +1,231 @@ +/** + * 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.submit.lookup; + +import java.util.LinkedList; +import java.util.List; + +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.dspace.submit.util.SubmissionLookupPublication; +import org.w3c.dom.Element; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class CrossRefUtils +{ + + /** + * + */ + public CrossRefUtils() + { + // TODO Auto-generated constructor stub + } + + public static Record convertCrossRefDomToRecord(Element dataRoot) + { + MutableRecord record = new SubmissionLookupPublication(""); + + String status = dataRoot.getAttribute("status"); + if (!"resolved".equals(status)) + { + String msg = XMLUtils.getElementValue(dataRoot, "msg"); + String exMsg = status + " - " + msg; + throw new RuntimeException(exMsg); + } + + String doi = XMLUtils.getElementValue(dataRoot, "doi"); + if (doi != null) + record.addValue("doi", new StringValue(doi)); + + String itemType = doi != null ? XMLUtils.getElementAttribute(dataRoot, + "doi", "type") : "unspecified"; + if (itemType != null) + record.addValue("doiType", new StringValue(itemType)); + + List<Element> identifier = XMLUtils.getElementList(dataRoot, "issn"); + for (Element ident : identifier) + { + if ("print".equalsIgnoreCase(ident.getAttribute("type")) + || StringUtils.isNotBlank(ident.getAttribute("type"))) + { + String issn = ident.getTextContent().trim(); + if (issn != null) + record.addValue("printISSN", new StringValue(issn)); + } + else + { + String eissn = ident.getTextContent().trim(); + if (eissn != null) + record.addValue("electronicISSN", new StringValue(eissn)); + } + } + + List<Element> identifierisbn = XMLUtils.getElementList(dataRoot, "isbn"); + for (Element ident : identifierisbn) + { + if ("print".equalsIgnoreCase(ident.getAttribute("type")) + || StringUtils.isNotBlank(ident.getAttribute("type"))) + { + String issn = ident.getTextContent().trim(); + if (issn != null) + record.addValue("printISBN", new StringValue(issn)); + } + else + { + String eissn = ident.getTextContent().trim(); + if (eissn != null) + record.addValue("electronicISBN", new StringValue(eissn)); + } + } + + String editionNumber = XMLUtils.getElementValue(dataRoot, + "editionNumber"); + if (editionNumber != null) + record.addValue("editionNumber", new StringValue(editionNumber)); + + String volume = XMLUtils.getElementValue(dataRoot, "volume"); + if (volume != null) + record.addValue("volume", new StringValue(volume)); + + String issue = XMLUtils.getElementValue(dataRoot, "issue"); + if (issue != null) + record.addValue("issue", new StringValue(issue)); + + String year = XMLUtils.getElementValue(dataRoot, "year"); + if (year != null) + record.addValue("year", new StringValue(year)); + + String firstPage = XMLUtils.getElementValue(dataRoot, "first_page"); + if (firstPage != null) + record.addValue("firstPage", new StringValue(firstPage)); + + String lastPage = XMLUtils.getElementValue(dataRoot, "last_page"); + if (lastPage != null) + record.addValue("lastPage", new StringValue(lastPage)); + + String seriesTitle = XMLUtils.getElementValue(dataRoot, "series_title"); + if (seriesTitle != null) + record.addValue("seriesTitle", new StringValue(seriesTitle)); + + String journalTitle = XMLUtils.getElementValue(dataRoot, + "journal_title"); + if (journalTitle != null) + record.addValue("journalTitle", new StringValue(journalTitle)); + + String volumeTitle = XMLUtils.getElementValue(dataRoot, "volume_title"); + if (volumeTitle != null) + record.addValue("volumeTitle", new StringValue(volumeTitle)); + + String articleTitle = XMLUtils.getElementValue(dataRoot, + "article_title"); + if (articleTitle != null) + record.addValue("articleTitle", new StringValue(articleTitle)); + + String publicationType = XMLUtils.getElementValue(dataRoot, + "pubblication_type"); + if (publicationType != null) + record.addValue("publicationType", new StringValue(publicationType)); + + List<String[]> authors = new LinkedList<String[]>(); + List<String[]> editors = new LinkedList<String[]>(); + List<String[]> translators = new LinkedList<String[]>(); + List<String[]> chairs = new LinkedList<String[]>(); + + List<Element> contributors = XMLUtils.getElementList(dataRoot, + "contributors"); + List<Element> contributor = null; + if (contributors != null && contributors.size() > 0) + { + contributor = XMLUtils.getElementList(contributors.get(0), + "contributor"); + + for (Element contrib : contributor) + { + + String givenName = XMLUtils.getElementValue(contrib, + "given_name"); + String surname = XMLUtils.getElementValue(contrib, "surname"); + + if ("editor".equalsIgnoreCase(contrib + .getAttribute("contributor_role"))) + { + editors.add(new String[] { givenName, surname }); + } + else if ("chair".equalsIgnoreCase(contrib + .getAttribute("contributor_role"))) + { + chairs.add(new String[] { givenName, surname }); + } + else if ("translator".equalsIgnoreCase(contrib + .getAttribute("contributor_role"))) + { + translators.add(new String[] { givenName, surname }); + } + else + { + authors.add(new String[] { givenName, surname }); + } + } + } + + if (authors.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String[] sArray : authors) + { + values.add(new StringValue(sArray[1] + ", " + sArray[0])); + } + record.addField("authors", values); + } + + if (editors.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String[] sArray : editors) + { + values.add(new StringValue(sArray[1] + ", " + sArray[0])); + } + record.addField("editors", values); + } + + if (translators.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String[] sArray : translators) + { + values.add(new StringValue(sArray[1] + ", " + sArray[0])); + } + record.addField("translators", values); + } + + if (chairs.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String[] sArray : chairs) + { + values.add(new StringValue(sArray[1] + ", " + sArray[0])); + } + record.addField("chairs", values); + } + return record; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/DSpaceWorkspaceItemOutputGenerator.java b/dspace-api/src/main/java/org/dspace/submit/lookup/DSpaceWorkspaceItemOutputGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..b25b1eb05f2fea04f35fa024d1919980a5e0d040 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/DSpaceWorkspaceItemOutputGenerator.java @@ -0,0 +1,439 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataOutputSpec; +import gr.ekt.bte.core.OutputGenerator; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.DCInput; +import org.dspace.app.util.DCInputSet; +import org.dspace.app.util.DCInputsReader; +import org.dspace.app.util.DCInputsReaderException; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.dspace.content.MetadataField; +import org.dspace.content.MetadataSchema; +import org.dspace.content.WorkspaceItem; +import org.dspace.core.Context; +import org.dspace.submit.util.ItemSubmissionLookupDTO; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class DSpaceWorkspaceItemOutputGenerator implements OutputGenerator +{ + + private static Logger log = Logger + .getLogger(DSpaceWorkspaceItemOutputGenerator.class); + + private Context context; + + private String formName; + + private List<WorkspaceItem> witems; + + private ItemSubmissionLookupDTO dto; + + private Collection collection; + + Map<String, String> outputMap; + + private List<String> extraMetadataToKeep; + + @Override + public List<String> generateOutput(RecordSet recordSet) + { + + log.info("BTE OutputGenerator started. Records to output: " + + recordSet.getRecords().size()); + + // Printing debug message + String totalString = ""; + for (Record record : recordSet.getRecords()) + { + totalString += SubmissionLookupUtils.getPrintableString(record) + + "\n"; + } + log.debug("Records to output:\n" + totalString); + + witems = new ArrayList<WorkspaceItem>(); + + for (Record rec : recordSet.getRecords()) + { + try + { + WorkspaceItem wi = WorkspaceItem.create(context, collection, + true); + merge(formName, wi.getItem(), rec); + + witems.add(wi); + + } + catch (AuthorizeException e) + { + log.error(e.getMessage(), e); + } + catch (SQLException e) + { + log.error(e.getMessage(), e); + } + catch (IOException e) + { + log.error(e.getMessage(), e); + } + + } + + return new ArrayList<String>(); + } + + @Override + public List<String> generateOutput(RecordSet records, DataOutputSpec spec) + { + return generateOutput(records); + } + + public List<WorkspaceItem> getWitems() + { + return witems; + } + + public void setContext(Context context) + { + this.context = context; + } + + public void setFormName(String formName) + { + this.formName = formName; + } + + public void setDto(ItemSubmissionLookupDTO dto) + { + this.dto = dto; + } + + public void setOutputMap(Map<String, String> outputMap) + { + // Reverse the key-value pairs + this.outputMap = new HashMap<String, String>(); + for (String key : outputMap.keySet()) + { + this.outputMap.put(outputMap.get(key), key); + } + } + + public void setCollection(Collection collection) + { + this.collection = collection; + } + + public void setExtraMetadataToKeep(List<String> extraMetadataToKeep) + { + this.extraMetadataToKeep = extraMetadataToKeep; + } + + // Methods + public void merge(String formName, Item item, Record record) + { + + Record itemLookup = record; + + Set<String> addedMetadata = new HashSet<String>(); + for (String field : itemLookup.getFields()) + { + String metadata = getMetadata(formName, itemLookup, field); + if (StringUtils.isBlank(metadata)) + { + continue; + } + if (item.getMetadata(metadata).length == 0 + || addedMetadata.contains(metadata)) + { + addedMetadata.add(metadata); + String[] md = splitMetadata(metadata); + if (isValidMetadata(formName, md)) + { // if in extra metadata or in the spefific form + List<Value> values = itemLookup.getValues(field); + if (values != null && values.size() > 0) + { + if (isRepeatableMetadata(formName, md)) + { // if metadata is repeatable in form + for (Value value : values) + { + String[] splitValue = splitValue(value + .getAsString()); + if (splitValue[3] != null) + { + item.addMetadata(md[0], md[1], md[2], + md[3], splitValue[0], + splitValue[1], + Integer.parseInt(splitValue[2])); + } + else + { + item.addMetadata(md[0], md[1], md[2], + md[3], value.getAsString()); + } + } + } + else + { + String value = values.iterator().next() + .getAsString(); + String[] splitValue = splitValue(value); + if (splitValue[3] != null) + { + item.addMetadata(md[0], md[1], md[2], md[3], + splitValue[0], splitValue[1], + Integer.parseInt(splitValue[2])); + } + else + { + item.addMetadata(md[0], md[1], md[2], md[3], + value); + } + } + } + } + } + } + + try + { + item.update(); + } + catch (SQLException e) + { + log.error(e.getMessage(), e); + } + catch (AuthorizeException e) + { + log.error(e.getMessage(), e); + } + + } + + private String getMetadata(String formName, Record itemLookup, String name) + { + String type = SubmissionLookupService.getType(itemLookup); + + String md = outputMap.get(type + "." + name); + if (StringUtils.isBlank(md)) + { + md = outputMap.get(formName + "." + name); + if (StringUtils.isBlank(md)) + { + md = outputMap.get(name); + } + } + + // KSTA:ToDo: Make this a modifier + if (md != null && md.contains("|")) + { + String[] cond = md.trim().split("\\|"); + for (int idx = 1; idx < cond.length; idx++) + { + boolean temp = itemLookup.getFields().contains(cond[idx]); + if (temp) + { + return null; + } + } + return cond[0]; + } + return md; + } + + private String[] splitMetadata(String metadata) + { + String[] mdSplit = new String[3]; + if (StringUtils.isNotBlank(metadata)) + { + String tmpSplit[] = metadata.split("\\."); + if (tmpSplit.length == 4) + { + mdSplit = new String[4]; + mdSplit[0] = tmpSplit[0]; + mdSplit[1] = tmpSplit[1]; + mdSplit[2] = tmpSplit[2]; + mdSplit[3] = tmpSplit[3]; + } + else if (tmpSplit.length == 3) + { + mdSplit = new String[4]; + mdSplit[0] = tmpSplit[0]; + mdSplit[1] = tmpSplit[1]; + mdSplit[2] = tmpSplit[2]; + mdSplit[3] = null; + } + else if (tmpSplit.length == 2) + { + mdSplit = new String[4]; + mdSplit[0] = tmpSplit[0]; + mdSplit[1] = tmpSplit[1]; + mdSplit[2] = null; + mdSplit[3] = null; + } + } + return mdSplit; + } + + private boolean isValidMetadata(String formName, String[] md) + { + try + { + if (extraMetadataToKeep != null + && extraMetadataToKeep.contains(StringUtils.join( + Arrays.copyOfRange(md, 0, 3), "."))) + { + return true; + } + return getDCInput(formName, md[0], md[1], md[2]) != null; + } + catch (Exception e) + { + log.error(e.getMessage(), e); + } + return false; + } + + private DCInput getDCInput(String formName, String schema, String element, + String qualifier) throws DCInputsReaderException + { + DCInputSet dcinputset = new DCInputsReader().getInputs(formName); + for (int idx = 0; idx < dcinputset.getNumberPages(); idx++) + { + for (DCInput dcinput : dcinputset.getPageRows(idx, true, true)) + { + if (dcinput.getSchema().equals(schema) + && dcinput.getElement().equals(element) + && ((dcinput.getQualifier() != null && dcinput + .getQualifier().equals(qualifier)) + || (dcinput.getQualifier() == null && qualifier == null))) + { + return dcinput; + } + } + } + return null; + } + + private boolean isRepeatableMetadata(String formName, String[] md) + { + try + { + DCInput dcinput = getDCInput(formName, md[0], md[1], md[2]); + if (dcinput != null) + { + return dcinput.isRepeatable(); + } + return true; + } + catch (Exception e) + { + e.printStackTrace(); + } + return false; + } + + private String[] splitValue(String value) + { + String[] splitted = value + .split(SubmissionLookupService.SEPARATOR_VALUE_REGEX); + String[] result = new String[6]; + result[0] = splitted[0]; + result[2] = "-1"; + result[3] = "-1"; + result[4] = "-1"; + if (splitted.length > 1) + { + result[5] = "splitted"; + if (StringUtils.isNotBlank(splitted[1])) + { + result[1] = splitted[1]; + } + if (splitted.length > 2) + { + result[2] = String.valueOf(Integer.parseInt(splitted[2])); + if (splitted.length > 3) + { + result[3] = String.valueOf(Integer.parseInt(splitted[3])); + if (splitted.length > 4) + { + result[4] = String.valueOf(Integer + .parseInt(splitted[4])); + } + } + } + } + return result; + } + + private void makeSureMetadataExist(Context context, String schema, + String element, String qualifier) + { + try + { + context.turnOffAuthorisationSystem(); + boolean create = false; + MetadataSchema mdschema = MetadataSchema.find(context, schema); + MetadataField mdfield = null; + if (mdschema == null) + { + mdschema = new MetadataSchema( + SubmissionLookupService.SL_NAMESPACE_PREFIX + schema, + schema); + mdschema.create(context); + create = true; + } + else + { + mdfield = MetadataField.findByElement(context, + mdschema.getSchemaID(), element, qualifier); + } + + if (mdfield == null) + { + mdfield = new MetadataField(mdschema, element, qualifier, + "Campo utilizzato per la cache del provider submission-lookup: " + + schema); + mdfield.create(context); + create = true; + } + if (create) + { + context.commit(); + } + context.restoreAuthSystemState(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/FieldMergeModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/FieldMergeModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..1cdbc7ab07b6e9d936f19b76295086f2b95fd260 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/FieldMergeModifier.java @@ -0,0 +1,75 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.AbstractModifier; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.Value; + +import java.util.List; +import java.util.Map; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class FieldMergeModifier extends AbstractModifier +{ + private Map<String, List<String>> mergeFieldMap; + + public FieldMergeModifier() + { + super("FieldMergeModifier"); + } + + @Override + public Record modify(MutableRecord rec) + { + if (mergeFieldMap != null) + { + for (String target_field : mergeFieldMap.keySet()) + { + List<String> source_fields = mergeFieldMap.get(target_field); + for (String source_field : source_fields) + { + List<Value> values = rec.getValues(source_field); + if (values != null && values.size() > 0) + { + for (Value value : values) + { + rec.addValue(target_field, value); + } + } + // rec.removeField(source_field); + } + } + } + return rec; + } + + /** + * @return the merge_field_map + */ + public Map<String, List<String>> getMergeFieldMap() + { + return mergeFieldMap; + } + + /** + * @param merge_field_map + * the merge_field_map to set + */ + public void setMergeFieldMap(Map<String, List<String>> merge_field_map) + { + this.mergeFieldMap = merge_field_map; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..eed73aa31337f12f650d04e3c5c0c20f890b364f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/LanguageCodeModifier.java @@ -0,0 +1,89 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.AbstractModifier; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.MissingResourceException; + +/** + * Modifier to covert ISO 639-2 alpha-3 code to ISO 639-1 alpha-2 code + * + * @author Keiji Suzuki + */ +public class LanguageCodeModifier extends AbstractModifier +{ + private static Map<String, String> lang3to2 = null; + static + { + lang3to2 = new HashMap<String, String>(); + for (Locale locale : Locale.getAvailableLocales()) + { + try + { + lang3to2.put(locale.getISO3Language(), locale.getLanguage()); + } + catch (MissingResourceException e) + { + continue; + } + } + } + + public LanguageCodeModifier() + { + super("LanguageCodeModifier"); + } + + @Override + public Record modify(MutableRecord rec) + { + List<Value> old_values = rec.getValues("language"); + if (old_values == null || old_values.size() == 0) + { + return rec; + } + + List<Value> new_values = new ArrayList<Value>(); + for (Value value : old_values) + { + String lang3 = value.getAsString(); + String lang2 = lang3.length() == 3 ? getLang2(lang3) : lang3; + new_values.add(new StringValue(lang2)); + } + + rec.updateField("language", new_values); + + return rec; + } + + /** + * Covert ISO 639-2 alpha-3 code to ISO 639-1 alpha-2 code + * + * @param lang + * 3char language code + * + * @return String 2char language code ("other" unless code has 2 char code) + * + */ + private String getLang2(String lang3) + { + return lang3to2.containsKey(lang3) ? lang3to2.get(lang3) : "other"; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/LookupProvidersCheck.java b/dspace-api/src/main/java/org/dspace/submit/lookup/LookupProvidersCheck.java new file mode 100644 index 0000000000000000000000000000000000000000..5372b345ca4b2e1976127de7ce8b170043722dae --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/LookupProvidersCheck.java @@ -0,0 +1,45 @@ +/** + * 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.submit.lookup; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class LookupProvidersCheck +{ + private List<String> providersOk = new ArrayList<String>(); + + private List<String> providersErr = new ArrayList<String>(); + + public List<String> getProvidersOk() + { + return providersOk; + } + + public void setProvidersOk(List<String> providersOk) + { + this.providersOk = providersOk; + } + + public List<String> getProvidersErr() + { + return providersErr; + } + + public void setProvidersErr(List<String> providersErr) + { + this.providersErr = providersErr; + } + +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/MapConverterModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/MapConverterModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..a9dd1241106a85ffd5b12c34cb100e8942a96ffc --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/MapConverterModifier.java @@ -0,0 +1,214 @@ +/** + * 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.submit.lookup; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang.StringUtils; +import org.dspace.core.ConfigurationManager; +import org.dspace.services.ConfigurationService; + +import gr.ekt.bte.core.AbstractModifier; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class MapConverterModifier extends AbstractModifier +{ + + private String mappingFile; //The properties absolute filename + + private String converterNameFile; //The properties filename + + private ConfigurationService configurationService; + + private Map<String, String> mapping; + + private String defaultValue = ""; + + private List<String> fieldKeys; + + private Map<String, String> regexConfig = new HashMap<String, String>(); + + public final String REGEX_PREFIX = "regex."; + + public void init() { + this.mappingFile = configurationService.getProperty("dspace.dir") + File.separator + "config" + File.separator + "crosswalks" + File.separator + converterNameFile; + + this.mapping = new HashMap<String, String>(); + + FileInputStream fis = null; + try + { + fis = new FileInputStream(new File(mappingFile)); + Properties mapConfig = new Properties(); + mapConfig.load(fis); + fis.close(); + for (Object key : mapConfig.keySet()) + { + String keyS = (String)key; + if (keyS.startsWith(REGEX_PREFIX)) + { + String regex = keyS.substring(REGEX_PREFIX.length()); + String regReplace = mapping.get(keyS); + if (regReplace == null) + { + regReplace = ""; + } + else if (regReplace.equalsIgnoreCase("@ident@")) + { + regReplace = "$0"; + } + regexConfig.put(regex,regReplace); + } + if (mapConfig.getProperty(keyS) != null) + mapping.put(keyS, mapConfig.getProperty(keyS)); + else + mapping.put(keyS, ""); + } + } + catch (Exception e) + { + throw new IllegalArgumentException("", e); + } + finally + { + if (fis != null) + { + try + { + fis.close(); + } + catch (IOException ioe) + { + // ... + } + } + } + for (String keyS : mapping.keySet()) + { + if (keyS.startsWith(REGEX_PREFIX)) + { + String regex = keyS.substring(REGEX_PREFIX.length()); + String regReplace = mapping.get(keyS); + if (regReplace == null) + { + regReplace = ""; + } + else if (regReplace.equalsIgnoreCase("@ident@")) + { + regReplace = "$0"; + } + regexConfig.put(regex,regReplace); + } + } + } + /** + * @param name + */ + public MapConverterModifier(String name) + { + super(name); + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.AbstractModifier#modify(gr.ekt.bte.core.MutableRecord) + */ + @Override + public Record modify(MutableRecord record) + { + if (mapping != null && fieldKeys != null) + { + for (String key : fieldKeys) + { + List<Value> values = record.getValues(key); + + if (values == null) + continue; + + List<Value> newValues = new ArrayList<Value>(); + + for (Value value : values) + { + String stringValue = value.getAsString(); + + String tmp = ""; + if (mapping.containsKey(stringValue)) + { + tmp = mapping.get(stringValue); + } + else + { + tmp = defaultValue; + for (String regex : regexConfig.keySet()) + { + if (stringValue != null + && stringValue.matches(regex)) + { + tmp = stringValue.replaceAll(regex, + regexConfig.get(regex)); + } + } + } + + if ("@@ident@@".equals(tmp)) + { + newValues.add(new StringValue(stringValue)); + } + else if (StringUtils.isNotBlank(tmp)) + { + newValues.add(new StringValue(tmp)); + } + else + newValues.add(new StringValue(stringValue)); + } + + record.updateField(key, newValues); + } + } + + return record; + } + + + public void setFieldKeys(List<String> fieldKeys) + { + this.fieldKeys = fieldKeys; + } + + public void setDefaultValue(String defaultValue) + { + this.defaultValue = defaultValue; + } + + public void setConverterNameFile(String converterNameFile) + { + this.converterNameFile = converterNameFile; + } + public void setConfigurationService(ConfigurationService configurationService) + { + this.configurationService = configurationService; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/MultipleSubmissionLookupDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/MultipleSubmissionLookupDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..3bed2668f4a1a7c3e3864835e7f9ba88aa4c8d98 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/MultipleSubmissionLookupDataLoader.java @@ -0,0 +1,341 @@ +/** + * 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.submit.lookup; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.log4j.Logger; +import org.dspace.core.Context; + +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bte.exceptions.MalformedSourceException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class MultipleSubmissionLookupDataLoader implements DataLoader +{ + + private static Logger log = Logger + .getLogger(MultipleSubmissionLookupDataLoader.class); + + private static final String NOT_FOUND_DOI = "NOT-FOUND-DOI"; + + Map<String, DataLoader> dataloadersMap; + + // Depending on these values, the multiple data loader loads data from the + // appropriate providers + Map<String, Set<String>> identifiers = null; // Searching by identifiers + // (DOI ...) + + Map<String, Set<String>> searchTerms = null; // Searching by author, title, + // date + + String filename = null; // Uploading file + + String type = null; // the type of the upload file (bibtex, etc.) + + /* + * (non-Javadoc) + * + * @see gr.ekt.bte.core.DataLoader#getRecords() + */ + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + // KSTA:ToDo: Support timeout (problematic) providers + // List<String> timeoutProviders = new ArrayList<String>(); + for (String providerName : filterProviders().keySet()) + { + DataLoader provider = dataloadersMap.get(providerName); + RecordSet subRecordSet = provider.getRecords(); + recordSet.addAll(subRecordSet); + // Add in each record the provider name... a new provider doesn't + // need to know about it! + for (Record record : subRecordSet.getRecords()) + { + if (record.isMutable()) + { + record.makeMutable().addValue( + SubmissionLookupService.PROVIDER_NAME_FIELD, + new StringValue(providerName)); + } + } + } + + // Question: Do we want that in case of file data loader? + // for each publication in the record set, if it has a DOI, try to find + // extra pubs from the other providers + if (searchTerms != null + || (identifiers != null && !identifiers + .containsKey(SubmissionLookupDataLoader.DOI))) + { // Extend + Map<String, Set<String>> provider2foundDOIs = new HashMap<String, Set<String>>(); + List<String> foundDOIs = new ArrayList<String>(); + + for (Record publication : recordSet.getRecords()) + { + String providerName = SubmissionLookupUtils.getFirstValue( + publication, + SubmissionLookupService.PROVIDER_NAME_FIELD); + + String doi = null; + + if (publication.getValues(SubmissionLookupDataLoader.DOI) != null + && publication + .getValues(SubmissionLookupDataLoader.DOI) + .size() > 0) + doi = publication.getValues(SubmissionLookupDataLoader.DOI) + .iterator().next().getAsString(); + if (doi == null) + { + doi = NOT_FOUND_DOI; + } + else + { + doi = SubmissionLookupUtils.normalizeDOI(doi); + if (!foundDOIs.contains(doi)) + { + foundDOIs.add(doi); + } + Set<String> tmp = provider2foundDOIs.get(providerName); + if (tmp == null) + { + tmp = new HashSet<String>(); + provider2foundDOIs.put(providerName, tmp); + } + tmp.add(doi); + } + } + + for (String providerName : dataloadersMap.keySet()) + { + DataLoader genProvider = dataloadersMap.get(providerName); + + if (!(genProvider instanceof SubmissionLookupDataLoader)) + { + continue; + } + + SubmissionLookupDataLoader provider = (SubmissionLookupDataLoader) genProvider; + + // Provider must support DOI + if (!provider.getSupportedIdentifiers().contains( + SubmissionLookupDataLoader.DOI)) + { + continue; + } + + // if (evictProviders != null + // && evictProviders.contains(provider.getShortName())) { + // continue; + // } + Set<String> doiToSearch = new HashSet<String>(); + Set<String> alreadyFoundDOIs = provider2foundDOIs + .get(providerName); + for (String doi : foundDOIs) + { + if (alreadyFoundDOIs == null + || !alreadyFoundDOIs.contains(doi)) + { + doiToSearch.add(doi); + } + } + List<Record> pPublications = null; + Context context = null; + try + { + if (doiToSearch.size() > 0) + { + context = new Context(); + pPublications = provider.getByDOIs(context, doiToSearch); + } + } + catch (Exception e) + { + log.error(e.getMessage(), e); + } + finally { + if(context!=null && context.isValid()) { + context.abort(); + } + } + if (pPublications != null) + { + for (Record rec : pPublications) + { + recordSet.addRecord(rec); + if (rec.isMutable()) + { + rec.makeMutable().addValue( + SubmissionLookupService.PROVIDER_NAME_FIELD, + new StringValue(providerName)); + } + } + + } + } + } + + log.info("BTE DataLoader finished. Items loaded: " + + recordSet.getRecords().size()); + + // Printing debug message + String totalString = ""; + for (Record record : recordSet.getRecords()) + { + totalString += SubmissionLookupUtils.getPrintableString(record) + + "\n"; + } + log.debug("Records loaded:\n" + totalString); + + return recordSet; + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec) + */ + @Override + public RecordSet getRecords(DataLoadingSpec loadingSpec) + throws MalformedSourceException + { + + if (loadingSpec.getOffset() > 0) // Identify the end of loading + return new RecordSet(); + + return getRecords(); + } + + public Map<String, DataLoader> getProvidersMap() + { + return dataloadersMap; + } + + public void setDataloadersMap(Map<String, DataLoader> providersMap) + { + this.dataloadersMap = providersMap; + } + + public void setIdentifiers(Map<String, Set<String>> identifiers) + { + this.identifiers = identifiers; + this.filename = null; + this.searchTerms = null; + + if (dataloadersMap != null) + { + for (String providerName : dataloadersMap.keySet()) + { + DataLoader provider = dataloadersMap.get(providerName); + if (provider instanceof NetworkSubmissionLookupDataLoader) + { + ((NetworkSubmissionLookupDataLoader) provider) + .setIdentifiers(identifiers); + } + + } + } + } + + public void setSearchTerms(Map<String, Set<String>> searchTerms) + { + this.searchTerms = searchTerms; + this.identifiers = null; + this.filename = null; + + if (dataloadersMap != null) + { + for (String providerName : dataloadersMap.keySet()) + { + DataLoader provider = dataloadersMap.get(providerName); + if (provider instanceof NetworkSubmissionLookupDataLoader) + { + ((NetworkSubmissionLookupDataLoader) provider) + .setSearchTerms(searchTerms); + } + } + } + } + + public void setFile(String filename, String type) + { + this.filename = filename; + this.type = type; + this.identifiers = null; + this.searchTerms = null; + + if (dataloadersMap != null) + { + for (String providerName : dataloadersMap.keySet()) + { + DataLoader provider = dataloadersMap.get(providerName); + if (provider instanceof FileDataLoader) + { + ((FileDataLoader) provider).setFilename(filename); + } + } + } + } + + public Map<String, DataLoader> filterProviders() + { + Map<String, DataLoader> result = new HashMap<String, DataLoader>(); + for (String providerName : dataloadersMap.keySet()) + { + DataLoader dataLoader = dataloadersMap.get(providerName); + if (searchTerms != null && identifiers == null && filename == null) + { + if (dataLoader instanceof SubmissionLookupDataLoader + && ((SubmissionLookupDataLoader) dataLoader) + .isSearchProvider()) + { + result.put(providerName, dataLoader); + } + } + else if (searchTerms == null && identifiers != null + && filename == null) + { + if (dataLoader instanceof SubmissionLookupDataLoader) + { + result.put(providerName, dataLoader); + } + } + else if (searchTerms == null && identifiers == null + && filename != null) + { + if (dataLoader instanceof FileDataLoader) + { + if (providerName.endsWith(type)) // add only the one that we + // are interested in + result.put(providerName, dataLoader); + } + } + } + + return result; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/NetworkSubmissionLookupDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/NetworkSubmissionLookupDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..be22f37111897f8bc0ba56b8f910545551080e3e --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/NetworkSubmissionLookupDataLoader.java @@ -0,0 +1,185 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; +import gr.ekt.bte.exceptions.MalformedSourceException; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.ParameterizedType; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.lang.StringUtils; +import org.dspace.core.Context; +import org.dspace.submit.util.SubmissionLookupPublication; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public abstract class NetworkSubmissionLookupDataLoader implements + SubmissionLookupDataLoader +{ + + Map<String, Set<String>> identifiers; // Searching by identifiers (DOI ...) + + Map<String, Set<String>> searchTerms; // Searching by author, title, date + + Map<String, String> fieldMap; // mapping between service fields and local + // intermediate fields + + String providerName; + + @Override + public List<Record> getByDOIs(Context context, Set<String> doiToSearch) + throws HttpException, IOException + { + + Map<String, Set<String>> keys = new HashMap<String, Set<String>>(); + keys.put(DOI, doiToSearch); + + return getByIdentifier(context, keys); + } + + // BTE Data Loader interface methods + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + List<Record> results = null; + + try + { + if (getIdentifiers() != null) + { // Search by identifiers + results = getByIdentifier(null, getIdentifiers()); + } + else + { + String title = getSearchTerms().get("title") != null ? getSearchTerms() + .get("title").iterator().next() + : null; + String authors = getSearchTerms().get("authors") != null ? getSearchTerms() + .get("authors").iterator().next() + : null; + String year = getSearchTerms().get("year") != null ? getSearchTerms() + .get("year").iterator().next() + : null; + int yearInt = Integer.parseInt(year); + results = search(null, title, authors, yearInt); + } + } + catch (HttpException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + if (results != null) + { + for (Record record : results) + { + recordSet.addRecord(record); + } + } + + return recordSet; + } + + @Override + public RecordSet getRecords(DataLoadingSpec arg0) + throws MalformedSourceException + { + + return getRecords(); + } + + public Map<String, Set<String>> getIdentifiers() + { + return identifiers; + } + + public void setIdentifiers(Map<String, Set<String>> identifiers) + { + this.identifiers = identifiers; + } + + public Map<String, Set<String>> getSearchTerms() + { + return searchTerms; + } + + public void setSearchTerms(Map<String, Set<String>> searchTerms) + { + this.searchTerms = searchTerms; + } + + public Map<String, String> getFieldMap() + { + return fieldMap; + } + + public void setFieldMap(Map<String, String> fieldMap) + { + this.fieldMap = fieldMap; + } + + public void setProviderName(String providerName) + { + this.providerName = providerName; + } + + public Record convertFields(Record publication) + { + for (String fieldName : fieldMap.keySet()) + { + String md = null; + if (fieldMap != null) + { + md = this.fieldMap.get(fieldName); + } + + if (StringUtils.isBlank(md)) + { + continue; + } + else + { + md = md.trim(); + } + + if (publication.isMutable()) + { + List<Value> values = publication.getValues(fieldName); + publication.makeMutable().removeField(fieldName); + publication.makeMutable().addField(md, values); + } + } + + return publication; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedFileDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedFileDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..d8a99fad3858e70e4af395f10bb9cb52dead606b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedFileDataLoader.java @@ -0,0 +1,177 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bte.exceptions.MalformedSourceException; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.Map; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class PubmedFileDataLoader extends FileDataLoader +{ + + Map<String, String> fieldMap; // mapping between service fields and local + // intermediate fields + + /** + * + */ + public PubmedFileDataLoader() + { + } + + /** + * @param filename + */ + public PubmedFileDataLoader(String filename) + { + super(filename); + } + + /* + * (non-Javadoc) + * + * @see gr.ekt.bte.core.DataLoader#getRecords() + */ + @Override + public RecordSet getRecords() throws MalformedSourceException + { + + RecordSet recordSet = new RecordSet(); + + try + { + InputStream inputStream = new FileInputStream(new File(filename)); + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document inDoc = builder.parse(inputStream); + + Element xmlRoot = inDoc.getDocumentElement(); + List<Element> pubArticles = XMLUtils.getElementList(xmlRoot, + "PubmedArticle"); + + for (Element xmlArticle : pubArticles) + { + Record record = null; + try + { + record = PubmedUtils.convertPubmedDomToRecord(xmlArticle); + recordSet.addRecord(convertFields(record)); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + } + catch (FileNotFoundException e) + { + e.printStackTrace(); + } + catch (ParserConfigurationException e) + { + e.printStackTrace(); + } + catch (SAXException e) + { + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + return recordSet; + + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.DataLoader#getRecords(gr.ekt.bte.core.DataLoadingSpec) + */ + @Override + public RecordSet getRecords(DataLoadingSpec spec) + throws MalformedSourceException + { + if (spec.getOffset() > 0) + { + return new RecordSet(); + } + return getRecords(); + } + + public Record convertFields(Record publication) + { + for (String fieldName : fieldMap.keySet()) + { + String md = null; + if (fieldMap != null) + { + md = this.fieldMap.get(fieldName); + } + + if (StringUtils.isBlank(md)) + { + continue; + } + else + { + md = md.trim(); + } + + if (publication.isMutable()) + { + List<Value> values = publication.getValues(fieldName); + publication.makeMutable().removeField(fieldName); + publication.makeMutable().addField(md, values); + } + } + + return publication; + } + + public void setFieldMap(Map<String, String> fieldMap) + { + this.fieldMap = fieldMap; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedOnlineDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedOnlineDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..85c996404eccbeeebf8b335459c90b97edafa1f4 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedOnlineDataLoader.java @@ -0,0 +1,139 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpException; +import org.apache.log4j.Logger; +import org.dspace.core.Context; +import org.dspace.core.LogManager; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class PubmedOnlineDataLoader extends NetworkSubmissionLookupDataLoader +{ + private boolean searchProvider = true; + + private static Logger log = Logger.getLogger(PubmedOnlineDataLoader.class); + + private PubmedService pubmedService = new PubmedService(); + + public void setPubmedService(PubmedService pubmedService) + { + this.pubmedService = pubmedService; + } + + @Override + public List<String> getSupportedIdentifiers() + { + return Arrays.asList(new String[] { PUBMED, DOI }); + } + + public void setSearchProvider(boolean searchProvider) + { + this.searchProvider = searchProvider; + } + + @Override + public boolean isSearchProvider() + { + return searchProvider; + } + + @Override + public List<Record> getByIdentifier(Context context, + Map<String, Set<String>> keys) throws HttpException, IOException + { + Set<String> pmids = keys != null ? keys.get(PUBMED) : null; + Set<String> dois = keys != null ? keys.get(DOI) : null; + List<Record> results = new ArrayList<Record>(); + if (pmids != null && pmids.size() > 0 + && (dois == null || dois.size() == 0)) + { + for (String pmid : pmids) + { + Record p = null; + try + { + p = pubmedService.getByPubmedID(pmid); + } + catch (Exception e) + { + log.error(LogManager.getHeader(context, "getByIdentifier", + "pmid=" + pmid), e); + } + if (p != null) + results.add(convertFields(p)); + } + } + else if (dois != null && dois.size() > 0 + && (pmids == null || pmids.size() == 0)) + { + StringBuffer query = new StringBuffer(); + for (String d : dois) + { + if (query.length() > 0) + { + query.append(" OR "); + } + query.append(d).append("[AI]"); + } + + List<Record> pubmedResults = pubmedService.search(query.toString()); + for (Record p : pubmedResults) + { + results.add(convertFields(p)); + } + } + else if (dois != null && dois.size() > 0 && pmids != null + && pmids.size() > 0) + { + // EKT:ToDo: support list of dois and pmids in the search method of + // pubmedService + List<Record> pubmedResults = pubmedService.search(dois.iterator() + .next(), pmids.iterator().next()); + if (pubmedResults != null) + { + for (Record p : pubmedResults) + { + results.add(convertFields(p)); + } + } + } + + return results; + } + + @Override + public List<Record> search(Context context, String title, String author, + int year) throws HttpException, IOException + { + List<Record> pubmedResults = pubmedService.search(title, author, year); + List<Record> results = new ArrayList<Record>(); + if (pubmedResults != null) + { + for (Record p : pubmedResults) + { + results.add(convertFields(p)); + } + } + return results; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedService.java b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedService.java new file mode 100644 index 0000000000000000000000000000000000000000..d493672f349bc42e5883cdff58e501ac1eb92f4d --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedService.java @@ -0,0 +1,300 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.XMLUtils; +import org.dspace.core.ConfigurationManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class PubmedService +{ + + private static Logger log = Logger.getLogger(PubmedService.class); + + private int timeout = 1000; + + public void setTimeout(int timeout) + { + this.timeout = timeout; + } + + public Record getByPubmedID(String pubmedid) throws HttpException, + IOException, ParserConfigurationException, SAXException + { + List<String> ids = new ArrayList<String>(); + ids.add(pubmedid.trim()); + List<Record> items = getByPubmedIDs(ids); + if (items != null && items.size() > 0) + { + return items.get(0); + } + return null; + } + + public List<Record> search(String title, String author, int year) + throws HttpException, IOException + { + StringBuffer query = new StringBuffer(); + if (StringUtils.isNotBlank(title)) + { + query.append("((").append(title).append("[TI]) OR ("); + // [TI] non funziona sempre, titolo di capitoli di libro + query.append("(").append(title).append("[book]))"); + } + if (StringUtils.isNotBlank(author)) + { + // [FAU] + if (query.length() > 0) + query.append(" AND "); + query.append("(").append(author).append("[AU])"); + } + if (year != -1) + { + // [DP] + if (query.length() > 0) + query.append(" AND "); + query.append(year).append("[DP]"); + } + return search(query.toString()); + } + + public List<Record> search(String query) throws IOException, HttpException + { + List<Record> results = null; + if (!ConfigurationManager.getBooleanProperty(SubmissionLookupService.CFG_MODULE, "remoteservice.demo")) + { + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + client.setTimeout(timeout); + method = new GetMethod( + "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi"); + + NameValuePair db = new NameValuePair("db", "pubmed"); + NameValuePair datetype = new NameValuePair("datetype", "edat"); + NameValuePair retmax = new NameValuePair("retmax", "10"); + NameValuePair queryParam = new NameValuePair("term", + query.toString()); + method.setQueryString(new NameValuePair[] { db, queryParam, + retmax, datetype }); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + throw new RuntimeException("WS call failed: " + + method.getStatusLine()); + } + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder builder; + try + { + builder = factory.newDocumentBuilder(); + + Document inDoc = builder.parse(method + .getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + Element idList = XMLUtils.getSingleElement(xmlRoot, + "IdList"); + List<String> pubmedIDs = XMLUtils.getElementValueList( + idList, "Id"); + results = getByPubmedIDs(pubmedIDs); + } + catch (ParserConfigurationException e1) + { + log.error(e1.getMessage(), e1); + } + catch (SAXException e1) + { + log.error(e1.getMessage(), e1); + } + } + catch (Exception e1) + { + log.error(e1.getMessage(), e1); + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } + else + { + InputStream stream = null; + try + { + File file = new File( + ConfigurationManager.getProperty("dspace.dir") + + "/config/crosswalks/demo/pubmed-search.xml"); + stream = new FileInputStream(file); + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document inDoc = builder.parse(stream); + + Element xmlRoot = inDoc.getDocumentElement(); + Element idList = XMLUtils.getSingleElement(xmlRoot, "IdList"); + List<String> pubmedIDs = XMLUtils.getElementValueList(idList, + "Id"); + results = getByPubmedIDs(pubmedIDs); + } + catch (Exception e) + { + throw new RuntimeException(e.getMessage(), e); + } + finally + { + if (stream != null) + { + try + { + stream.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + } + return results; + } + + public List<Record> getByPubmedIDs(List<String> pubmedIDs) + throws HttpException, IOException, ParserConfigurationException, + SAXException + { + List<Record> results = new ArrayList<Record>(); + GetMethod method = null; + try + { + HttpClient client = new HttpClient(); + client.setTimeout(5 * timeout); + method = new GetMethod( + "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi"); + + NameValuePair db = new NameValuePair("db", "pubmed"); + NameValuePair retmode = new NameValuePair("retmode", "xml"); + NameValuePair rettype = new NameValuePair("rettype", "full"); + NameValuePair id = new NameValuePair("id", StringUtils.join( + pubmedIDs.iterator(), ",")); + method.setQueryString(new NameValuePair[] { db, retmode, + rettype, id }); + // Execute the method. + int statusCode = client.executeMethod(method); + + if (statusCode != HttpStatus.SC_OK) + { + throw new RuntimeException("WS call failed: " + + method.getStatusLine()); + } + + DocumentBuilderFactory factory = DocumentBuilderFactory + .newInstance(); + factory.setValidating(false); + factory.setIgnoringComments(true); + factory.setIgnoringElementContentWhitespace(true); + + DocumentBuilder builder = factory.newDocumentBuilder(); + Document inDoc = builder + .parse(method.getResponseBodyAsStream()); + + Element xmlRoot = inDoc.getDocumentElement(); + List<Element> pubArticles = XMLUtils.getElementList(xmlRoot, + "PubmedArticle"); + + for (Element xmlArticle : pubArticles) + { + Record pubmedItem = null; + try + { + pubmedItem = PubmedUtils + .convertPubmedDomToRecord(xmlArticle); + results.add(pubmedItem); + } + catch (Exception e) + { + throw new RuntimeException( + "PubmedID is not valid or not exist: " + + e.getMessage(), e); + } + } + + return results; + } + finally + { + if (method != null) + { + method.releaseConnection(); + } + } + } + + public List<Record> search(String doi, String pmid) throws HttpException, + IOException + { + StringBuffer query = new StringBuffer(); + if (StringUtils.isNotBlank(doi)) + { + query.append(doi); + query.append("[AID]"); + } + if (StringUtils.isNotBlank(pmid)) + { + // [FAU] + if (query.length() > 0) + query.append(" OR "); + query.append(pmid).append("[PMID]"); + } + return search(query.toString()); + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedUtils.java b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..552db676effb0f470f2986a410a5588fedb2f522 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/PubmedUtils.java @@ -0,0 +1,347 @@ +/** + * 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.submit.lookup; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import org.apache.commons.lang.StringUtils; +import org.dspace.app.util.XMLUtils; +import org.dspace.submit.util.SubmissionLookupPublication; +import org.w3c.dom.Element; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class PubmedUtils +{ + + public static Record convertPubmedDomToRecord(Element pubArticle) + { + MutableRecord record = new SubmissionLookupPublication(""); + + Map<String, String> monthToNum = new HashMap<String, String>(); + monthToNum.put("Jan", "01"); + monthToNum.put("Feb", "02"); + monthToNum.put("Mar", "03"); + monthToNum.put("Apr", "04"); + monthToNum.put("May", "05"); + monthToNum.put("Jun", "06"); + monthToNum.put("Jul", "07"); + monthToNum.put("Aug", "08"); + monthToNum.put("Sep", "09"); + monthToNum.put("Oct", "10"); + monthToNum.put("Nov", "11"); + monthToNum.put("Dec", "12"); + + Element medline = XMLUtils.getSingleElement(pubArticle, + "MedlineCitation"); + + Element article = XMLUtils.getSingleElement(medline, "Article"); + Element pubmed = XMLUtils.getSingleElement(pubArticle, "PubmedData"); + + Element identifierList = XMLUtils.getSingleElement(pubmed, + "ArticleIdList"); + if (identifierList != null) + { + List<Element> identifiers = XMLUtils.getElementList(identifierList, + "ArticleId"); + if (identifiers != null) + { + for (Element id : identifiers) + { + if ("pubmed".equals(id.getAttribute("IdType"))) + { + String pubmedID = id.getTextContent().trim(); + if (pubmedID != null) + record.addValue("pubmedID", new StringValue( + pubmedID)); + } + else if ("doi".equals(id.getAttribute("IdType"))) + { + String doi = id.getTextContent().trim(); + if (doi != null) + record.addValue("doi", new StringValue(doi)); + } + } + } + } + + String status = XMLUtils.getElementValue(pubmed, "PublicationStatus"); + if (status != null) + record.addValue("publicationStatus", new StringValue(status)); + + String pubblicationModel = XMLUtils.getElementAttribute(medline, + "Article", "PubModel"); + if (pubblicationModel != null) + record.addValue("pubModel", new StringValue( + pubblicationModel)); + + String title = XMLUtils.getElementValue(article, "ArticleTitle"); + if (title != null) + record.addValue("articleTitle", new StringValue(title)); + + Element abstractElement = XMLUtils + .getSingleElement(article, "Abstract"); + if (abstractElement == null) + { + abstractElement = XMLUtils.getSingleElement(medline, + "OtherAbstract"); + } + if (abstractElement != null) + { + String summary = XMLUtils.getElementValue(abstractElement, + "AbstractText"); + if (summary != null) + record.addValue("abstractText", new StringValue(summary)); + } + + List<String[]> authors = new LinkedList<String[]>(); + Element authorList = XMLUtils.getSingleElement(article, "AuthorList"); + if (authorList != null) + { + List<Element> authorsElement = XMLUtils.getElementList(authorList, + "Author"); + if (authorsElement != null) + { + for (Element author : authorsElement) + { + if (StringUtils.isBlank(XMLUtils.getElementValue(author, + "CollectiveName"))) + { + authors.add(new String[] { + XMLUtils.getElementValue(author, "ForeName"), + XMLUtils.getElementValue(author, "LastName") }); + } + } + } + } + if (authors.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String[] sArray : authors) + { + values.add(new StringValue(sArray[1] + ", " + sArray[0])); + } + record.addField("author", values); + } + + Element journal = XMLUtils.getSingleElement(article, "Journal"); + if (journal != null) + { + List<Element> jnumbers = XMLUtils.getElementList(journal, "ISSN"); + if (jnumbers != null) + { + for (Element jnumber : jnumbers) + { + if ("Print".equals(jnumber.getAttribute("IssnType"))) + { + String issn = jnumber.getTextContent().trim(); + if (issn != null) + record.addValue("printISSN", new StringValue(issn)); + } + else + { + String eissn = jnumber.getTextContent().trim(); + if (eissn != null) + record.addValue("electronicISSN", new StringValue(eissn)); + } + } + } + + String journalTitle = XMLUtils.getElementValue(journal, "Title"); + if (journalTitle != null) + record.addValue("journalTitle", new StringValue(journalTitle)); + + Element journalIssueElement = XMLUtils.getSingleElement(journal, + "JournalIssue"); + if (journalIssueElement != null) + { + String volume = XMLUtils.getElementValue(journalIssueElement, + "Volume"); + if (volume != null) + record.addValue("journalVolume", new StringValue(volume)); + + String issue = XMLUtils.getElementValue(journalIssueElement, + "Issue"); + if (issue != null) + record.addValue("journalIssue", new StringValue(issue)); + + Element pubDateElement = XMLUtils.getSingleElement( + journalIssueElement, "PubDate"); + + String pubDate = null; + if (pubDateElement != null) + { + pubDate = XMLUtils.getElementValue(pubDateElement, "Year"); + + String mounth = XMLUtils.getElementValue(pubDateElement, + "Month"); + String day = XMLUtils + .getElementValue(pubDateElement, "Day"); + if (StringUtils.isNotBlank(mounth) + && monthToNum.containsKey(mounth)) + { + pubDate += "-" + monthToNum.get(mounth); + if (StringUtils.isNotBlank(day)) + { + pubDate += "-" + (day.length() == 1 ? "0" + day : day); + } + } + } + if (pubDate == null){ + pubDate = XMLUtils.getElementValue(pubDateElement, "MedlineDate"); + } + if (pubDate != null) + record.addValue("pubDate", new StringValue(pubDate)); + } + + String language = XMLUtils.getElementValue(article, "Language"); + if (language != null) + record.addValue("language", new StringValue(language)); + + List<String> type = new LinkedList<String>(); + Element publicationTypeList = XMLUtils.getSingleElement(article, + "PublicationTypeList"); + if (publicationTypeList != null) + { + List<Element> publicationTypes = XMLUtils.getElementList( + publicationTypeList, "PublicationType"); + for (Element publicationType : publicationTypes) + { + type.add(publicationType.getTextContent().trim()); + } + } + if (type.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : type) + { + values.add(new StringValue(s)); + } + record.addField("publicationType", values); + } + + List<String> primaryKeywords = new LinkedList<String>(); + List<String> secondaryKeywords = new LinkedList<String>(); + Element keywordsList = XMLUtils.getSingleElement(medline, + "KeywordList"); + if (keywordsList != null) + { + List<Element> keywords = XMLUtils.getElementList(keywordsList, + "Keyword"); + for (Element keyword : keywords) + { + if ("Y".equals(keyword.getAttribute("MajorTopicYN"))) + { + primaryKeywords.add(keyword.getTextContent().trim()); + } + else + { + secondaryKeywords.add(keyword.getTextContent().trim()); + } + } + } + if (primaryKeywords.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : primaryKeywords) + { + values.add(new StringValue(s)); + } + record.addField("primaryKeyword", values); + } + if (secondaryKeywords.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : secondaryKeywords) + { + values.add(new StringValue(s)); + } + record.addField("secondaryKeyword", values); + } + + List<String> primaryMeshHeadings = new LinkedList<String>(); + List<String> secondaryMeshHeadings = new LinkedList<String>(); + Element meshHeadingsList = XMLUtils.getSingleElement(medline, + "MeshHeadingList"); + if (meshHeadingsList != null) + { + List<Element> meshHeadings = XMLUtils.getElementList( + meshHeadingsList, "MeshHeading"); + for (Element meshHeading : meshHeadings) + { + if ("Y".equals(XMLUtils.getElementAttribute(meshHeading, + "DescriptorName", "MajorTopicYN"))) + { + primaryMeshHeadings.add(XMLUtils.getElementValue( + meshHeading, "DescriptorName")); + } + else + { + secondaryMeshHeadings.add(XMLUtils.getElementValue( + meshHeading, "DescriptorName")); + } + } + } + if (primaryMeshHeadings.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : primaryMeshHeadings) + { + values.add(new StringValue(s)); + } + record.addField("primaryMeshHeading", values); + } + if (secondaryMeshHeadings.size() > 0) + { + List<Value> values = new LinkedList<Value>(); + for (String s : secondaryMeshHeadings) + { + values.add(new StringValue(s)); + } + record.addField("secondaryMeshHeading", values); + } + + Element paginationElement = XMLUtils.getSingleElement(article, + "Pagination"); + if (paginationElement != null) + { + String startPage = XMLUtils.getElementValue(paginationElement, + "StartPage"); + String endPage = XMLUtils.getElementValue(paginationElement, + "EndPage"); + if (StringUtils.isBlank(startPage)) + { + startPage = XMLUtils.getElementValue(paginationElement, + "MedlinePgn"); + } + + if (startPage != null) + record.addValue("startPage", new StringValue(startPage)); + if (endPage != null) + record.addValue("endPage", new StringValue(endPage)); + } + } + + return record; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/RemoveLastDotModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/RemoveLastDotModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..f29ca1375454233c303cbbb8a146ec7a6217cb76 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/RemoveLastDotModifier.java @@ -0,0 +1,87 @@ +/** + * 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.submit.lookup; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +import gr.ekt.bte.core.AbstractModifier; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class RemoveLastDotModifier extends AbstractModifier +{ + + List<String> fieldKeys; + + /** + * @param name + */ + public RemoveLastDotModifier(String name) + { + super(name); + } + + /* + * (non-Javadoc) + * + * @see + * gr.ekt.bte.core.AbstractModifier#modify(gr.ekt.bte.core.MutableRecord) + */ + @Override + public Record modify(MutableRecord record) + { + if (fieldKeys != null) + { + for (String key : fieldKeys) + { + List<Value> values = record.getValues(key); + + List<Value> newValues = new ArrayList<Value>(); + + if (values != null) + { + for (Value value : values) + { + String valueString = value.getAsString(); + if (StringUtils.isNotBlank(valueString) + && valueString.endsWith(".")) + { + newValues.add(new StringValue(valueString + .substring(0, valueString.length() - 1))); + } + else + { + newValues.add(new StringValue(valueString)); + } + } + + record.updateField(key, newValues); + } + } + } + + return record; + } + + public void setFieldKeys(List<String> fieldKeys) + { + this.fieldKeys = fieldKeys; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionItemDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionItemDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..9908e887ad2eb584b102d22b0bd011f6c978446a --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionItemDataLoader.java @@ -0,0 +1,118 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.DataLoadingSpec; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.exceptions.MalformedSourceException; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.dspace.submit.util.ItemSubmissionLookupDTO; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionItemDataLoader implements DataLoader +{ + private List<ItemSubmissionLookupDTO> dtoList; + + List<DataLoader> providers; + + private static Logger log = Logger + .getLogger(SubmissionItemDataLoader.class); + + public SubmissionItemDataLoader() + { + dtoList = null; + providers = null; + } + + @Override + public RecordSet getRecords() throws MalformedSourceException + { + if (dtoList == null) + { + throw new MalformedSourceException("dtoList not initialized"); + } + RecordSet ret = new RecordSet(); + + for (ItemSubmissionLookupDTO dto : dtoList) + { + Record rec = dto.getTotalPublication(providers); + ret.addRecord(rec); + } + + log.info("BTE DataLoader finished. Items loaded: " + + ret.getRecords().size()); + + // Printing debug message + String totalString = ""; + for (Record record : ret.getRecords()) + { + totalString += SubmissionLookupUtils.getPrintableString(record) + + "\n"; + } + log.debug("Records loaded:\n" + totalString); + + return ret; + } + + @Override + public RecordSet getRecords(DataLoadingSpec spec) + throws MalformedSourceException + { + if (spec.getOffset() > 0) + { + return new RecordSet(); + } + + return getRecords(); + } + + /** + * @return the dtoList + */ + public List<ItemSubmissionLookupDTO> getDtoList() + { + return dtoList; + } + + /** + * @param dtoList + * the dtoList to set + */ + public void setDtoList(List<ItemSubmissionLookupDTO> dtoList) + { + this.dtoList = dtoList; + } + + /** + * @return the providers + */ + public List<DataLoader> getProviders() + { + return providers; + } + + /** + * @param providers + * the providers to set + */ + public void setProviders(List<DataLoader> providers) + { + this.providers = providers; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupDataLoader.java b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupDataLoader.java new file mode 100644 index 0000000000000000000000000000000000000000..df6f453ef758b038f7f46c9d7f169bf463f14839 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupDataLoader.java @@ -0,0 +1,57 @@ +/** + * 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.submit.lookup; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.httpclient.HttpException; +import org.dspace.core.Context; + +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.Record; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public interface SubmissionLookupDataLoader extends DataLoader +{ + + public final static String DOI = "doi"; + + public final static String PUBMED = "pubmed"; + + public final static String ARXIV = "arxiv"; + + public final static String REPEC = "repec"; + + public final static String SCOPUSEID = "scopuseid"; + + public final static String CINII = "cinii"; + + public final static String TYPE = "type"; + + List<String> getSupportedIdentifiers(); + + boolean isSearchProvider(); + + List<Record> search(Context context, String title, String author, int year) + throws HttpException, IOException; + + List<Record> getByIdentifier(Context context, Map<String, Set<String>> keys) + throws HttpException, IOException; + + List<Record> getByDOIs(Context context, Set<String> doiToSearch) + throws HttpException, IOException; + +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupOutputGenerator.java b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupOutputGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..23dca88324ac224d6ba09c097a35a6383e2683e8 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupOutputGenerator.java @@ -0,0 +1,107 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataOutputSpec; +import gr.ekt.bte.core.OutputGenerator; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.RecordSet; +import gr.ekt.bte.core.Value; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.dspace.submit.util.ItemSubmissionLookupDTO; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupOutputGenerator implements OutputGenerator +{ + private List<ItemSubmissionLookupDTO> dtoList; + + private static final String DOI_FIELD = "doi"; + + private static final String NOT_FOUND_DOI = "NOT-FOUND-DOI"; + + public SubmissionLookupOutputGenerator() + { + + } + + @Override + public List<String> generateOutput(RecordSet records) + { + dtoList = new ArrayList<ItemSubmissionLookupDTO>(); + + Map<String, List<Record>> record_sets = new HashMap<String, List<Record>>(); + int counter = 0; + for (Record rec : records) + { + String current_doi = NOT_FOUND_DOI; + List<Value> values = rec.getValues(DOI_FIELD); + if (values != null && values.size() > 0) + { + current_doi = values.get(0).getAsString(); + } + else + { + current_doi = NOT_FOUND_DOI + "_" + counter; + } + + if (record_sets.keySet().contains(current_doi)) + { + record_sets.get(current_doi).add(rec); + } + else + { + ArrayList<Record> publication = new ArrayList<Record>(); + publication.add(rec); + record_sets.put(current_doi, publication); + } + + counter++; + } + for (Map.Entry<String, List<Record>> entry : record_sets.entrySet()) + { + ItemSubmissionLookupDTO dto = new ItemSubmissionLookupDTO( + entry.getValue()); + dtoList.add(dto); + } + + return new ArrayList<String>(); + } + + @Override + public List<String> generateOutput(RecordSet records, DataOutputSpec spec) + { + return generateOutput(records); + } + + /** + * @return the items + */ + public List<ItemSubmissionLookupDTO> getDtoList() + { + return dtoList; + } + + /** + * @param items + * the items to set + */ + public void setDtoList(List<ItemSubmissionLookupDTO> items) + { + this.dtoList = items; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupService.java b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupService.java new file mode 100644 index 0000000000000000000000000000000000000000..b3a6334d553f0e977811d6d3b9a3218a3169e97b --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupService.java @@ -0,0 +1,225 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.TransformationEngine; +import gr.ekt.bte.dataloader.FileDataLoader; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; +import org.dspace.submit.util.SubmissionLookupDTO; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupService +{ + public static final String CFG_MODULE = "submission-lookup"; + + public static final String SL_NAMESPACE_PREFIX = "http://www.dspace.org/sl/"; + + public static final String MANUAL_USER_INPUT = "manual"; + + public static final String PROVIDER_NAME_FIELD = "provider_name_field"; + + private static Logger log = Logger.getLogger(SubmissionLookupService.class); + + public static final String SEPARATOR_VALUE = "#######"; + + public static final String SEPARATOR_VALUE_REGEX = SEPARATOR_VALUE; + + private List<DataLoader> providers; + + private Map<String, List<String>> idents2provs; + + private List<String> searchProviders; + + private List<String> fileProviders; + + private TransformationEngine phase1TransformationEngine; + + private TransformationEngine phase2TransformationEngine; + + private List<String> detailFields = null; + + public void setPhase2TransformationEngine( + TransformationEngine phase2TransformationEngine) + { + this.phase2TransformationEngine = phase2TransformationEngine; + } + + public void setPhase1TransformationEngine( + TransformationEngine phase1TransformationEngine) + { + this.phase1TransformationEngine = phase1TransformationEngine; + + MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) phase1TransformationEngine + .getDataLoader(); + + this.idents2provs = new HashMap<String, List<String>>(); + this.searchProviders = new ArrayList<String>(); + this.fileProviders = new ArrayList<String>(); + + if (providers == null) + { + this.providers = new ArrayList<DataLoader>(); + + for (String providerName : dataLoader.getProvidersMap().keySet()) + { + DataLoader p = dataLoader.getProvidersMap().get(providerName); + + this.providers.add(p); + + // Do not do that for file providers + if (p instanceof FileDataLoader) + { + this.fileProviders.add(providerName); + } + else if (p instanceof NetworkSubmissionLookupDataLoader) + { + + NetworkSubmissionLookupDataLoader p2 = (NetworkSubmissionLookupDataLoader) p; + + p2.setProviderName(providerName); + + if (p2.isSearchProvider()) + { + searchProviders.add(providerName); + } + List<String> suppIdentifiers = p2.getSupportedIdentifiers(); + if (suppIdentifiers != null) + { + for (String ident : suppIdentifiers) + { + List<String> tmp = idents2provs.get(ident); + if (tmp == null) + { + tmp = new ArrayList<String>(); + idents2provs.put(ident, tmp); + } + tmp.add(providerName); + } + } + } + } + } + } + + public TransformationEngine getPhase1TransformationEngine() + { + return phase1TransformationEngine; + } + + public TransformationEngine getPhase2TransformationEngine() + { + return phase2TransformationEngine; + } + + public List<String> getIdentifiers() + { + + List<String> allSupportedIdentifiers = new ArrayList<String>(); + MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) phase1TransformationEngine + .getDataLoader(); + for (String providerName : dataLoader.getProvidersMap().keySet()) + { + DataLoader provider = dataLoader.getProvidersMap() + .get(providerName); + if (provider instanceof SubmissionLookupDataLoader) + { + for (String identifier : ((SubmissionLookupDataLoader) provider) + .getSupportedIdentifiers()) + { + if (!allSupportedIdentifiers.contains(identifier)) + { + allSupportedIdentifiers.add(identifier); + } + } + } + } + + return allSupportedIdentifiers; + } + + public Map<String, List<String>> getProvidersIdentifiersMap() + { + return idents2provs; + } + + public SubmissionLookupDTO getSubmissionLookupDTO( + HttpServletRequest request, String uuidSubmission) + { + SubmissionLookupDTO dto = (SubmissionLookupDTO) request.getSession() + .getAttribute("submission_lookup_" + uuidSubmission); + if (dto == null) + { + dto = new SubmissionLookupDTO(); + storeDTOs(request, uuidSubmission, dto); + } + return dto; + } + + public void invalidateDTOs(HttpServletRequest request, String uuidSubmission) + { + request.getSession().removeAttribute( + "submission_lookup_" + uuidSubmission); + } + + public void storeDTOs(HttpServletRequest request, String uuidSubmission, + SubmissionLookupDTO dto) + { + request.getSession().setAttribute( + "submission_lookup_" + uuidSubmission, dto); + } + + public List<String> getSearchProviders() + { + return searchProviders; + } + + public List<DataLoader> getProviders() + { + return providers; + } + + public static String getProviderName(Record rec) + { + return SubmissionLookupUtils.getFirstValue(rec, + SubmissionLookupService.PROVIDER_NAME_FIELD); + } + + public static String getType(Record rec) + { + return SubmissionLookupUtils.getFirstValue(rec, + SubmissionLookupDataLoader.TYPE); + } + + public List<String> getFileProviders() + { + return this.fileProviders; + } + + public List<String> getDetailFields() { + return detailFields; + } + + public void setDetailFields(List<String> detailFields) { + this.detailFields = detailFields; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupUtils.java b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..81e98e335ea8ec9162c3854f47aa5ecb14285d17 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/SubmissionLookupUtils.java @@ -0,0 +1,162 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.Value; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +import org.apache.log4j.Logger; +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchema; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupUtils +{ + private static Logger log = Logger.getLogger(SubmissionLookupUtils.class); + + /** Location of config file */ + private static final String configFilePath = ConfigurationManager + .getProperty("dspace.dir") + + File.separator + + "config" + + File.separator + "crosswalks" + File.separator; + + // Patter to extract the converter name if any + private static final Pattern converterPattern = Pattern + .compile(".*\\((.*)\\)"); + + public static LookupProvidersCheck getProvidersCheck(Context context, + Item item, String dcSchema, String dcElement, String dcQualifier) + { + try + { + LookupProvidersCheck check = new LookupProvidersCheck(); + MetadataSchema[] schemas = MetadataSchema.findAll(context); + DCValue[] values = item.getMetadata(dcSchema, dcElement, + dcQualifier, Item.ANY); + + for (MetadataSchema schema : schemas) + { + boolean error = false; + if (schema.getNamespace().startsWith( + SubmissionLookupService.SL_NAMESPACE_PREFIX)) + { + DCValue[] slCache = item.getMetadata(schema.getName(), + dcElement, dcQualifier, Item.ANY); + if (slCache.length == 0) + continue; + + if (slCache.length != values.length) + { + error = true; + } + else + { + for (int idx = 0; idx < values.length; idx++) + { + DCValue v = values[idx]; + DCValue sl = slCache[idx]; + // FIXME gestire authority e possibilita' multiple: + // match non sicuri, affiliation, etc. + if (!v.value.equals(sl.value)) + { + error = true; + break; + } + } + } + if (error) + { + check.getProvidersErr().add(schema.getName()); + } + else + { + check.getProvidersOk().add(schema.getName()); + } + } + } + return check; + } + catch (Exception e) + { + log.error(e.getMessage(), e); + throw new RuntimeException(e.getMessage(), e); + } + + } + + public static String normalizeDOI(String doi) + { + if (doi != null) + { + return doi.trim().replaceAll("^http://dx.doi.org/", "") + .replaceAll("^doi:", ""); + } + return null; + + } + + public static String getFirstValue(Record rec, String field) + { + List<Value> values = rec.getValues(field); + String value = null; + if (values != null && values.size() > 0) + { + value = values.get(0).getAsString(); + } + return value; + } + + public static List<String> getValues(Record rec, String field) + { + List<String> result = new ArrayList<String>(); + List<Value> values = rec.getValues(field); + if (values != null && values.size() > 0) + { + for (Value value : values) + { + result.add(value.getAsString()); + } + } + return result; + } + + public static String getPrintableString(Record record) + { + StringBuilder result = new StringBuilder(); + + result.append("\nPublication {\n"); + + for (String field : record.getFields()) + { + result.append("--" + field + ":\n"); + List<Value> values = record.getValues(field); + for (Value value : values) + { + result.append("\t" + value.getAsString() + "\n"); + } + } + + result.append("}\n"); + + return result.toString(); + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/lookup/ValueConcatenationModifier.java b/dspace-api/src/main/java/org/dspace/submit/lookup/ValueConcatenationModifier.java new file mode 100644 index 0000000000000000000000000000000000000000..32f36f2ab726bb37673135dc47c0ab94898768ab --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/lookup/ValueConcatenationModifier.java @@ -0,0 +1,113 @@ +/** + * 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.submit.lookup; + +import gr.ekt.bte.core.AbstractModifier; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; + +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class ValueConcatenationModifier extends AbstractModifier +{ + private String field; + + private String separator = ","; + + private boolean whitespaceAfter = true; + + public ValueConcatenationModifier() + { + super("ValueConcatenationModifier"); + } + + @Override + public Record modify(MutableRecord rec) + { + List<Value> values = rec.getValues(field); + if (values != null) + { + List<String> converted_values = new ArrayList<String>(); + for (Value val : values) + { + converted_values.add(val.getAsString()); + } + List<Value> final_value = new ArrayList<Value>(); + String v = StringUtils.join(converted_values.iterator(), separator + + (whitespaceAfter ? " " : "")); + final_value.add(new StringValue(v)); + rec.updateField(field, final_value); + } + + return rec; + } + + /** + * @return the field + */ + public String getField() + { + return field; + } + + /** + * @param field + * the field to set + */ + public void setField(String field) + { + this.field = field; + } + + /** + * @return the separator + */ + public String getSeparator() + { + return separator; + } + + /** + * @param separator + * the separator to set + */ + public void setSeparator(String separator) + { + this.separator = separator; + } + + /** + * @return the whiteSpaceAfter + */ + public boolean isWhitespaceAfter() + { + return whitespaceAfter; + } + + /** + * @param whiteSpaceAfter + * the whiteSpaceAfter to set + */ + public void setWhitespaceAfter(boolean whiteSpaceAfter) + { + this.whitespaceAfter = whiteSpaceAfter; + } +} 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/StartSubmissionLookupStep.java b/dspace-api/src/main/java/org/dspace/submit/step/StartSubmissionLookupStep.java new file mode 100644 index 0000000000000000000000000000000000000000..efe4f2f0a63e7e7ff800e7623faf3aad08143159 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/step/StartSubmissionLookupStep.java @@ -0,0 +1,311 @@ +/** + * 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.submit.step; + +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.TransformationEngine; +import gr.ekt.bte.core.TransformationSpec; +import gr.ekt.bte.exceptions.BadTransformationSpec; +import gr.ekt.bte.exceptions.MalformedSourceException; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.DCInputSet; +import org.dspace.app.util.DCInputsReader; +import org.dspace.app.util.SubmissionInfo; +import org.dspace.app.util.Util; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.WorkspaceItem; +import org.dspace.core.Context; +import org.dspace.submit.AbstractProcessingStep; +import org.dspace.submit.lookup.DSpaceWorkspaceItemOutputGenerator; +import org.dspace.submit.lookup.SubmissionItemDataLoader; +import org.dspace.submit.lookup.SubmissionLookupService; +import org.dspace.submit.util.ItemSubmissionLookupDTO; +import org.dspace.submit.util.SubmissionLookupDTO; +import org.dspace.submit.util.SubmissionLookupPublication; +import org.dspace.utils.DSpace; + +/** + * StartSubmissionLookupStep is used when you want enabled the user to auto fill + * the item in submission with metadata retrieved from external bibliographic + * services (like pubmed, arxiv, and so on...) + * + * <p> + * At the moment this step is only available for JSPUI + * </p> + * + * @see org.dspace.app.util.SubmissionConfig + * @see org.dspace.app.util.SubmissionStepConfig + * @see org.dspace.submit.AbstractProcessingStep + * + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + * @version $Revision$ + */ +public class StartSubmissionLookupStep extends AbstractProcessingStep +{ + /*************************************************************************** + * 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) + **************************************************************************/ + // no collection was selected + public static final int STATUS_NO_COLLECTION = 1; + + // invalid collection or error finding collection + public static final int STATUS_INVALID_COLLECTION = 2; + + public static final int STATUS_NO_SUUID = 3; + + public static final int STATUS_SUBMISSION_EXPIRED = 4; + + private SubmissionLookupService slService = new DSpace() + .getServiceManager().getServiceByName( + SubmissionLookupService.class.getCanonicalName(), + SubmissionLookupService.class); + + /** log4j logger */ + private static Logger log = Logger + .getLogger(StartSubmissionLookupStep.class); + + /** + * Do any processing of the information input by the user, and/or perform + * step processing (if no user interaction required) + * <P> + * It is this method's job to save any data to the underlying database, as + * necessary, and return error messages (if any) which can then be processed + * by the appropriate user interface (JSP-UI or XML-UI) + * <P> + * NOTE: If this step is a non-interactive step (i.e. requires no UI), then + * it should perform *all* of its processing in this method! + * + * @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 + * doPostProcessing() below! (if STATUS_COMPLETE or 0 is returned, + * no errors occurred!) + */ + public int doProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + throws ServletException, IOException, SQLException, + AuthorizeException + { + // First we find the collection which was selected + int id = Util.getIntParameter(request, "collectionid"); + String titolo = request.getParameter("search_title"); + String date = request.getParameter("search_year"); + String autori = request.getParameter("search_authors"); + String uuidSubmission = request.getParameter("suuid"); + String uuidLookup = request.getParameter("iuuid"); + String fuuidLookup = request.getParameter("fuuid"); + + if (StringUtils.isBlank(uuidSubmission)) + { + return STATUS_NO_SUUID; + } + + SubmissionLookupDTO submissionDTO = slService.getSubmissionLookupDTO( + request, uuidSubmission); + + if (submissionDTO == null) + { + return STATUS_SUBMISSION_EXPIRED; + } + + ItemSubmissionLookupDTO itemLookup = null; + if (fuuidLookup == null || fuuidLookup.isEmpty()) + { + if (StringUtils.isNotBlank(uuidLookup)) + { + itemLookup = submissionDTO.getLookupItem(uuidLookup); + if (itemLookup == null) + { + return STATUS_SUBMISSION_EXPIRED; + } + } + } + // if the user didn't select a collection, + // send him/her back to "select a collection" page + if (id < 0) + { + return STATUS_NO_COLLECTION; + } + + // try to load the collection + Collection col = Collection.find(context, id); + + // Show an error if the collection is invalid + if (col == null) + { + return STATUS_INVALID_COLLECTION; + } + else + { + // create our new Workspace Item + DCInputSet inputSet = null; + try + { + inputSet = new DCInputsReader().getInputs(col.getHandle()); + } + catch (Exception e) + { + log.error(e.getMessage(), e); + throw new RuntimeException(e); + } + + List<ItemSubmissionLookupDTO> dto = new ArrayList<ItemSubmissionLookupDTO>(); + + if (itemLookup != null) + { + dto.add(itemLookup); + } + else if (fuuidLookup != null && !fuuidLookup.isEmpty()) + { + String[] ss = fuuidLookup.split(","); + for (String s : ss) + { + itemLookup = submissionDTO.getLookupItem(s); + if (itemLookup == null) + { + return STATUS_SUBMISSION_EXPIRED; + } + dto.add(itemLookup); + } + } + else + { + SubmissionLookupPublication manualPub = new SubmissionLookupPublication( + SubmissionLookupService.MANUAL_USER_INPUT); + manualPub.add("title", titolo); + manualPub.add("year", date); + manualPub.add("allauthors", autori); + + Enumeration e = request.getParameterNames(); + + while (e.hasMoreElements()) + { + String parameterName = (String) e.nextElement(); + String parameterValue = request.getParameter(parameterName); + + if (parameterName.startsWith("identifier_") + && StringUtils.isNotBlank(parameterValue)) + { + manualPub + .add(parameterName.substring("identifier_" + .length()), parameterValue); + } + } + List<Record> publications = new ArrayList<Record>(); + publications.add(manualPub); + dto.add(new ItemSubmissionLookupDTO(publications)); + + } + + List<WorkspaceItem> result = null; + + TransformationEngine transformationEngine = slService + .getPhase2TransformationEngine(); + if (transformationEngine != null) + { + SubmissionItemDataLoader dataLoader = (SubmissionItemDataLoader) transformationEngine + .getDataLoader(); + dataLoader.setDtoList(dto); + // dataLoader.setProviders() + + DSpaceWorkspaceItemOutputGenerator outputGenerator = (DSpaceWorkspaceItemOutputGenerator) transformationEngine + .getOutputGenerator(); + outputGenerator.setCollection(col); + outputGenerator.setContext(context); + outputGenerator.setFormName(inputSet.getFormName()); + outputGenerator.setDto(dto.get(0)); + + try + { + transformationEngine.transform(new TransformationSpec()); + result = outputGenerator.getWitems(); + } + catch (BadTransformationSpec e1) + { + e1.printStackTrace(); + } + catch (MalformedSourceException e1) + { + e1.printStackTrace(); + } + } + + if (result != null && result.size() > 0) + { + // update Submission Information with this Workspace Item + subInfo.setSubmissionItem(result.iterator().next()); + } + + // commit changes to database + context.commit(); + + // need to reload current submission process config, + // since it is based on the Collection selected + subInfo.reloadSubmissionConfig(request); + } + + slService.invalidateDTOs(request, uuidSubmission); + // no errors occurred + 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 + { + // there is always just one page in the "select a collection" step! + return 1; + } +} 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/submit/util/ItemSubmissionLookupDTO.java b/dspace-api/src/main/java/org/dspace/submit/util/ItemSubmissionLookupDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..cb4cd642169db688aa9e3e1c2ed4412c95a46e4f --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/util/ItemSubmissionLookupDTO.java @@ -0,0 +1,111 @@ +/** + * 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.submit.util; + +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.Value; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import org.dspace.submit.lookup.SubmissionLookupDataLoader; +import org.dspace.submit.lookup.SubmissionLookupService; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class ItemSubmissionLookupDTO implements Serializable +{ + private static final long serialVersionUID = 1; + + private static final String MERGED_PUBLICATION_PROVIDER = "merged"; + + private static final String UNKNOWN_PROVIDER_STRING = "UNKNOWN-PROVIDER"; + + private List<Record> publications; + + private String uuid; + + public ItemSubmissionLookupDTO(List<Record> publications) + { + this.uuid = UUID.randomUUID().toString(); + this.publications = publications; + } + + public List<Record> getPublications() + { + return publications; + } + + public Set<String> getProviders() + { + Set<String> orderedProviders = new LinkedHashSet<String>(); + for (Record p : publications) + { + orderedProviders.add(SubmissionLookupService.getProviderName(p)); + } + return orderedProviders; + } + + public String getUUID() + { + return uuid; + } + + public Record getTotalPublication(List<DataLoader> providers) + { + if (publications == null) + { + return null; + } + else if (publications.size() == 1) + { + return publications.get(0); + } + else + { + MutableRecord pub = new SubmissionLookupPublication( + MERGED_PUBLICATION_PROVIDER); + // for (SubmissionLookupProvider prov : providers) + // { + for (Record p : publications) + { + // if + // (!SubmissionLookupService.getProviderName(p).equals(prov.getShortName())) + // { + // continue; + // } + for (String field : p.getFields()) + { + List<Value> values = p.getValues(field); + if (values != null && values.size() > 0) + { + if (!pub.getFields().contains(field)) + { + for (Value v : values) + { + pub.addValue(field, v); + } + } + } + } + } + // } + return pub; + } + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupDTO.java b/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..599d7ecd5b784e75d0d5635e842b265557242954 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupDTO.java @@ -0,0 +1,52 @@ +/** + * 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.submit.util; + +import java.io.Serializable; +import java.util.List; +import java.util.UUID; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupDTO implements Serializable +{ + private static final long serialVersionUID = 1; + + private String uuid; + + private List<ItemSubmissionLookupDTO> items; + + public SubmissionLookupDTO() + { + this.uuid = UUID.randomUUID().toString(); + } + + public void setItems(List<ItemSubmissionLookupDTO> items) + { + this.items = items; + } + + public ItemSubmissionLookupDTO getLookupItem(String uuidLookup) + { + if (items != null) + { + for (ItemSubmissionLookupDTO item : items) + { + if (item.getUUID().equals(uuidLookup)) + { + return item; + } + } + } + return null; + } +} diff --git a/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupPublication.java b/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupPublication.java new file mode 100644 index 0000000000000000000000000000000000000000..5b6d287a2e0e01b83984447ea7bedf421b0d4125 --- /dev/null +++ b/dspace-api/src/main/java/org/dspace/submit/util/SubmissionLookupPublication.java @@ -0,0 +1,231 @@ +/** + * 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.submit.util; + +import gr.ekt.bte.core.MutableRecord; +import gr.ekt.bte.core.StringValue; +import gr.ekt.bte.core.Value; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.dspace.submit.lookup.SubmissionLookupDataLoader; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupPublication implements MutableRecord, Serializable +{ + private String providerName; + + private Map<String, List<String>> storage = new HashMap<String, List<String>>(); + + public SubmissionLookupPublication(String providerName) + { + this.providerName = providerName; + } + + // needed to serialize it with JSON + public Map<String, List<String>> getStorage() + { + return storage; + } + + public Set<String> getFields() + { + return storage.keySet(); + } + + public List<String> remove(String md) + { + return storage.remove(md); + } + + public void add(String md, String nValue) + { + if (StringUtils.isNotBlank(nValue)) + { + List<String> tmp = storage.get(md); + if (tmp == null) + { + tmp = new ArrayList<String>(); + storage.put(md, tmp); + } + tmp.add(nValue); + } + } + + public String getFirstValue(String md) + { + List<String> tmp = storage.get(md); + if (tmp == null || tmp.size() == 0) + { + return null; + } + return tmp.get(0); + } + + public String getProviderName() + { + return providerName; + } + + public String getType() + { + return getFirstValue(SubmissionLookupDataLoader.TYPE); + } + + // BTE Record interface methods + @Override + public boolean hasField(String md) + { + return storage.containsKey(md); + } + + @Override + public List<Value> getValues(String md) + { + List<String> stringValues = storage.get(md); + if (stringValues == null) + { + return null; + } + List<Value> values = new ArrayList<Value>(); + for (String value : stringValues) + { + values.add(new StringValue(value)); + } + return values; + } + + @Override + public boolean isMutable() + { + return true; + } + + @Override + public MutableRecord makeMutable() + { + return this; + } + + @Override + public boolean addField(String md, List<Value> values) + { + if (storage.containsKey(md)) + { + List<String> stringValues = storage.get(md); + if (values != null) + { + for (Value value : values) + { + stringValues.add(value.getAsString()); + } + } + } + else + { + List<String> tmp = new ArrayList<String>(); + if (values != null) + { + for (Value value : values) + { + tmp.add(value.getAsString()); + } + } + storage.put(md, tmp); + } + + return true; + } + + @Override + public boolean addValue(String md, Value value) + { + if (storage.containsKey(md)) + { + List<String> stringValues = storage.get(md); + stringValues.add(value.getAsString()); + } + else + { + List<String> tmp = new ArrayList<String>(); + tmp.add(value.getAsString()); + + storage.put(md, tmp); + } + + return true; + } + + @Override + public boolean removeField(String md) + { + if (storage.containsKey(md)) + { + storage.remove(md); + } + return false; + } + + @Override + public boolean removeValue(String md, Value value) + { + if (storage.containsKey(md)) + { + List<String> stringValues = storage.get(md); + stringValues.remove(value.getAsString()); + } + return true; + } + + @Override + public boolean updateField(String md, List<Value> values) + { + List<String> stringValues = new ArrayList<String>(); + for (Value value : values) + { + stringValues.add(value.getAsString()); + } + storage.put(md, stringValues); + + return true; + } + + @Override + public boolean updateValue(String md, Value valueOld, Value valueNew) + { + if (storage.containsKey(md)) + { + List<String> stringValues = storage.get(md); + List<String> newStringValues = storage.get(md); + for (String s : stringValues) + { + if (s.equals(valueOld.getAsString())) + { + newStringValues.add(valueNew.getAsString()); + } + else + { + newStringValues.add(s); + } + } + storage.put(md, newStringValues); + } + return true; + } +} 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/main/resources/maven.properties b/dspace-api/src/main/resources/maven.properties new file mode 100644 index 0000000000000000000000000000000000000000..d256fe231d858511c5945221f6bafeef0e3f4976 --- /dev/null +++ b/dspace-api/src/main/resources/maven.properties @@ -0,0 +1,9 @@ +# +# 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/ +# + +maven.version = ${maven.version} diff --git a/dspace-api/src/main/resources/scm.properties b/dspace-api/src/main/resources/scm.properties new file mode 100644 index 0000000000000000000000000000000000000000..319ff3a928f1b9e99e8c047c8adc186d7a5e4239 --- /dev/null +++ b/dspace-api/src/main/resources/scm.properties @@ -0,0 +1,10 @@ +# +# 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/ +# + +revision = ${buildNumber} +branch = ${scmBranch} diff --git a/dspace-api/src/main/resources/spring/spring-dspace-addon-requestitem-services.xml b/dspace-api/src/main/resources/spring/spring-dspace-addon-requestitem-services.xml new file mode 100644 index 0000000000000000000000000000000000000000..c7e5c6f9ff49f2240677fd29c322decdb22d9f1c --- /dev/null +++ b/dspace-api/src/main/resources/spring/spring-dspace-addon-requestitem-services.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-2.5.xsd" + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + + <context:annotation-config /> <!-- allows us to use spring annotations in beans --> + + <bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy" + id="org.dspace.app.requestitem.RequestItemAuthorExtractor"> + <!-- + Uncomment these properties if you want lookup in metadata the email and the name of the author to contact for request copy. + If you don't configure that or if the requested item doesn't have these metadata the submitter data are used as fail over + + <property name="emailMetadata" value="schema.element.qualifier" /> + <property name="fullNameMatadata" value="schema.element.qualifier" /> + + --> + </bean> + +</beans> diff --git a/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-configuration-services.xml b/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-configuration-services.xml new file mode 100644 index 0000000000000000000000000000000000000000..00bf02a2b94f4475beb6329a2ffe23e07f56db8a --- /dev/null +++ b/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-configuration-services.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-2.5.xsd" + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + + <context:annotation-config /> <!-- allows us to use spring annotations in beans --> + + <bean class="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService" + id="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"> + <property name="issnItemExtractors"> + <list> + <bean class="org.dspace.app.sherpa.submit.MetadataValueISSNExtractor"> + <property name="metadataList"> + <list> + <value>dc.identifier.issn</value> + </list> + </property> + </bean> + <!-- Use the follow if you have the SHERPARoMEOJournalTitle enabled + <bean class="org.dspace.app.sherpa.submit.MetadataAuthorityISSNExtractor"> + <property name="metadataList"> + <list> + <value>dc.title.alternative</value> + </list> + </property> + </bean> --> + </list> + </property> + </bean> + +</beans> diff --git a/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-services.xml b/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-services.xml new file mode 100644 index 0000000000000000000000000000000000000000..e43be6bae7206c96e4cb15d025cc95e199393990 --- /dev/null +++ b/dspace-api/src/main/resources/spring/spring-dspace-addon-sherpa-services.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-2.5.xsd" + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + + <context:annotation-config /> <!-- allows us to use spring annotations in beans --> + + <bean class="org.dspace.app.sherpa.SHERPAService" id="org.dspace.app.sherpa.SHERPAService"/> + + <bean class="org.dspace.app.sherpa.submit.SHERPASubmitService" id="org.dspace.app.sherpa.submit.SHERPASubmitService"> + <property name="sherpaService" ref="org.dspace.app.sherpa.SHERPAService" /> + <property name="configuration" ref="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService" /> + </bean> +</beans> diff --git a/dspace-api/src/test/data/dspaceFolder/config/spiders/agents/dspace-agents-testing.txt b/dspace-api/src/test/data/dspaceFolder/config/spiders/agents/dspace-agents-testing.txt new file mode 100644 index 0000000000000000000000000000000000000000..74ba3c3d35dc75a3f39b66bd1b0979ec3a2953e6 --- /dev/null +++ b/dspace-api/src/test/data/dspaceFolder/config/spiders/agents/dspace-agents-testing.txt @@ -0,0 +1 @@ +^msnbot diff --git a/dspace-api/src/test/data/dspaceFolder/config/spiders/domains/dspace-domains-testing.txt b/dspace-api/src/test/data/dspaceFolder/config/spiders/domains/dspace-domains-testing.txt new file mode 100644 index 0000000000000000000000000000000000000000..e6d36e1191734151eb22740624732bdbf05023a4 --- /dev/null +++ b/dspace-api/src/test/data/dspaceFolder/config/spiders/domains/dspace-domains-testing.txt @@ -0,0 +1 @@ +^baiduspider-.*\.crawl\.baidu\.com diff --git a/dspace-api/src/test/data/dspaceFolder/config/spiders/dspace-address-testing.txt b/dspace-api/src/test/data/dspaceFolder/config/spiders/dspace-address-testing.txt new file mode 100644 index 0000000000000000000000000000000000000000..63dd1754d475dc120c2851795bf7b3eace48babe --- /dev/null +++ b/dspace-api/src/test/data/dspaceFolder/config/spiders/dspace-address-testing.txt @@ -0,0 +1,2 @@ +# For testing +192.168.2.1 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/discovery/MockIndexEventConsumer.java b/dspace-api/src/test/java/org/dspace/discovery/MockIndexEventConsumer.java new file mode 100644 index 0000000000000000000000000000000000000000..3d212b2eaad29b6927df29cb0eb846b44d5cd839 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/discovery/MockIndexEventConsumer.java @@ -0,0 +1,41 @@ +/** + * 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.discovery; + +import mockit.Mock; +import mockit.MockClass; +import org.dspace.core.Context; +import org.dspace.event.Event; + +/** + * Dummy Discovery IndexEventConsumer. It essentially does nothing, + * as Discovery/Solr is not actively running during unit testing. + * + * @author tdonohue + */ +@MockClass(realClass=IndexEventConsumer.class) +public class MockIndexEventConsumer { + + //public void initialize() throws Exception { + //do nothing + //} + + @Mock + public void consume(Context ctx, Event event) throws Exception { + //do nothing - Solr is not running during unit testing, so we cannot index test content in Solr + } + + @Mock + public void end(Context ctx) throws Exception { + //do nothing - Solr is not running during unit testing, so we cannot index test content in Solr + } + + //public void finish(Context ctx) throws Exception { + //do nothing + //} +} diff --git a/dspace-api/src/test/java/org/dspace/identifier/DOIIdentifierProviderTest.java b/dspace-api/src/test/java/org/dspace/identifier/DOIIdentifierProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4f4593e77fefd170415e2f24e8d5da058568dad7 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/DOIIdentifierProviderTest.java @@ -0,0 +1,711 @@ +/** + * 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.identifier; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Random; +import org.dspace.AbstractUnitTest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.*; +import org.dspace.core.Context; +import org.dspace.kernel.ServiceManager; +import org.dspace.services.ConfigurationService; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.dspace.workflow.WorkflowItem; +import org.dspace.workflow.WorkflowManager; +import org.junit.*; +import static org.junit.Assert.*; +import static org.junit.Assume.*; + +/** +* Tests for {@link DataCiteIdentifierProvider}. +* +* @author Mark H. Wood +* @author Pascal-Nicolas Becker +*/ +public class DOIIdentifierProviderTest + extends AbstractUnitTest +{ + private static final String PREFIX = "10.5072"; + private static final String NAMESPACE_SEPARATOR = "dspaceUnitTests-"; + + private static ServiceManager sm = null; + private static ConfigurationService config = null; + + private static Community community; + private static Collection collection; + + private static MockDOIConnector connector; + private DOIIdentifierProvider provider; + + /** The most recently created test Item's ID */ + private static int itemID; + + public DOIIdentifierProviderTest() + { + } + + private static void dumpMetadata(Item eyetem) + { + DCValue[] metadata = eyetem.getMetadata("dc", Item.ANY, Item.ANY, Item.ANY); + for (DCValue metadatum : metadata) + System.out.printf("Metadata: %s.%s.%s(%s) = %s\n", + metadatum.schema, + metadatum.element, + metadatum.qualifier, + metadatum.language, + metadatum.value); + } + + /** + * Create a fresh Item, installed in the repository. + * + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + private Item newItem(Context ctx) + throws SQLException, AuthorizeException, IOException + { + ctx.turnOffAuthorisationSystem(); + ctx.setCurrentUser(eperson); + + WorkspaceItem wsItem = WorkspaceItem.create(ctx, collection, false); + + WorkflowItem wfItem = WorkflowManager.start(ctx, wsItem); + WorkflowManager.advance(ctx, wfItem, ctx.getCurrentUser()); + + Item item = wfItem.getItem(); + item.addMetadata("dc", "contributor", "author", null, "Author, A. N."); + item.addMetadata("dc", "title", null, null, "A Test Object"); + item.addMetadata("dc", "publisher", null, null, "DSpace Test Harness"); + + // If DOIIdentifierProvider is configured + // (dspace/conf/spring/api/identifier-service.xml) the new created item + // gets automatically a DOI. We remove this DOI as it can make problems + // with the tests. + String sql = "DELETE FROM Doi WHERE resource_type_id = ? AND resource_id = ?"; + DatabaseManager.updateQuery(context, sql, item.getType(), item.getID()); + + DCValue[] metadata = item.getMetadata( + DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + List<String> remainder = new ArrayList<String>(); + + for (DCValue id : metadata) + { + if (!id.value.startsWith(DOI.RESOLVER)) + { + remainder.add(id.value); + } + } + + item.clearMetadata( + DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + item.addMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null, + remainder.toArray(new String[remainder.size()])); + + item.update(); + ctx.commit(); + ctx.restoreAuthSystemState(); + + return item; + } + + public String createDOI(Item item, Integer status, boolean metadata) + throws SQLException, IdentifierException, AuthorizeException + { + return this.createDOI(item, status, metadata, null); + } + + /** + * Create a DOI to an item. + * @param item Item the DOI should be created for. + * @param status The status of the DOI. + * @param metadata Whether the DOI should be included in the metadata of the item. + * @param doi The doi or null if we should generate one. + * @return the DOI + * @throws SQLException + */ + public String createDOI(Item item, Integer status, boolean metadata, String doi) + throws SQLException, IdentifierException, AuthorizeException + { + // we need some random data. UUIDs would be bloated here + Random random = new Random(); + if (null == doi) + { + doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + + Long.toHexString(new Date().getTime()) + "-" + + random.nextInt(997); + } + + TableRow doiRow = DatabaseManager.create(context, "Doi"); + doiRow.setColumn("doi", doi.substring(DOI.SCHEME.length())); + doiRow.setColumn("resource_type_id", item.getType()); + doiRow.setColumn("resource_id", item.getID()); + if (status == null) + { + doiRow.setColumnNull("status"); + } + else + { + doiRow.setColumn("status", status); + } + assumeTrue(1 == DatabaseManager.update(context, doiRow)); + + if (metadata) + { + item.addMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null, + DOI.DOIToExternalForm(doi)); + item.update(); + } + + context.commit(); + return doi; + } + + @BeforeClass + public static void setUpClass() + throws Exception + { + // Find the usual kernel services + sm = kernelImpl.getServiceManager(); + Context ctx = new Context(); + + ctx.turnOffAuthorisationSystem(); + ctx.setCurrentUser(eperson); + // Create an environment for our test objects to live in. + community = Community.create(null, ctx); + community.setMetadata("name", "A Test Community"); + community.update(); + collection = community.createCollection(); + collection.setMetadata("name", "A Test Collection"); + collection.update(); + ctx.complete(); + + config = kernelImpl.getConfigurationService(); + // Configure the service under test. + config.setProperty(DOIIdentifierProvider.CFG_PREFIX, PREFIX); + config.setProperty(DOIIdentifierProvider.CFG_NAMESPACE_SEPARATOR, + NAMESPACE_SEPARATOR); + // Don't try to send mail. + config.setProperty("mail.server.disabled", "true"); + + connector = new MockDOIConnector(); + } + + @AfterClass + public static void tearDownClass() + throws Exception + { + /* + System.out.print("Tearing down\n\n"); + Context ctx = new Context(); + dumpMetadata(Item.find(ctx, itemID)); + */ + } + + @Before + public void setUp() + { + context.setCurrentUser(eperson); + context.turnOffAuthorisationSystem(); + + provider = new DOIIdentifierProvider(); + provider.setConfigurationService(config); + provider.setDOIConnector(connector); + } + + @After + public void tearDown() + { + context.restoreAuthSystemState(); + connector.reset(); + } + + /** + * Test of supports method, of class DataCiteIdentifierProvider. + */ + @Test + public void testSupports_Class() + { + Class<? extends Identifier> identifier = DOI.class; + assertTrue("DOI should be supported", provider.supports(identifier)); + } + + @Test + public void testSupports_valid_String() + { + String[] validDOIs = new String[] + { + "10.5072/123abc-lkj/kljl", + PREFIX + "/" + NAMESPACE_SEPARATOR + "lkjljasd1234", + DOI.SCHEME + "10.5072/123abc-lkj/kljl", + "http://dx.doi.org/10.5072/123abc-lkj/kljl", + DOI.RESOLVER + "/10.5072/123abc-lkj/kljl" + }; + + for (String doi : validDOIs) + { + assertTrue("DOI should be supported", provider.supports(doi)); + } + } + + @Test + public void testDoes_not_support_invalid_String() + { + String[] invalidDOIs = new String[] + { + "11.5072/123abc-lkj/kljl", + "http://hdl.handle.net/handle/10.5072/123abc-lkj/kljl", + "", + null + }; + + for (String notADoi : invalidDOIs) + { + assertFalse("Invalid DOIs shouldn't be supported", + provider.supports(notADoi)); + } + } + + @Test + public void testStore_DOI_as_item_metadata() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + + Long.toHexString(new Date().getTime()); + provider.saveDOIToObject(context, item, doi); + + DCValue[] metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + boolean result = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi))) + { + result = true; + } + } + assertTrue("Cannot store DOI as item metadata value.", result); + } + + @Test + public void testGet_DOI_out_of_item_metadata() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + + Long.toHexString(new Date().getTime()); + + item.addMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null, + DOI.DOIToExternalForm(doi)); + item.update(); + context.commit(); + + assertTrue("Failed to recognize DOI in item metadata.", + doi.equals(DOIIdentifierProvider.getDOIOutOfObject(item))); + } + + @Test + public void testRemove_DOI_from_item_metadata() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi = DOI.SCHEME + PREFIX + "/" + NAMESPACE_SEPARATOR + + Long.toHexString(new Date().getTime()); + + item.addMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null, + DOI.DOIToExternalForm(doi)); + item.update(); + context.commit(); + + provider.removeDOIFromObject(context, item, doi); + + DCValue[] metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + boolean foundDOI = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi))) + { + foundDOI = true; + } + } + assertFalse("Cannot remove DOI from item metadata.", foundDOI); + } + + @Test + public void testGet_DOI_by_DSpaceObject() + throws SQLException, AuthorizeException, IOException, + IllegalArgumentException, IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false); + + String retrievedDOI = DOIIdentifierProvider.getDOIByObject(context, item); + + assertNotNull("Failed to load DOI by DSpaceObject.", retrievedDOI); + assertTrue("Loaded wrong DOI by DSpaceObject.", doi.equals(retrievedDOI)); + } + + @Test + public void testGet_DOI_lookup() + throws SQLException, AuthorizeException, IOException, + IllegalArgumentException, IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false); + + String retrievedDOI = provider.lookup(context, (DSpaceObject) item); + + assertNotNull("Failed to loookup doi.", retrievedDOI); + assertTrue("Loaded wrong DOI on lookup.", doi.equals(retrievedDOI)); + } + + @Test + public void testGet_DSpaceObject_by_DOI() + throws SQLException, AuthorizeException, IOException, + IllegalArgumentException, IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false); + + DSpaceObject dso = DOIIdentifierProvider.getObjectByDOI(context, doi); + + assertNotNull("Failed to load DSpaceObject by DOI.", dso); + if (item.getType() != dso.getType() || item.getID() != dso.getID()) + { + fail("Object loaded by DOI was another object then expected!"); + } + } + + @Test + public void testResolve_DOI() + throws SQLException, AuthorizeException, IOException, + IllegalArgumentException, IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, false); + + DSpaceObject dso = provider.resolve(context, doi); + + assertNotNull("Failed to resolve DOI.", dso); + if (item.getType() != dso.getType() || item.getID() != dso.getID()) + { + fail("Object return by DOI lookup was another object then expected!"); + } + } + + /* + * The following test seems a bit silly, but it was helpful to debug some + * problems while deleting DOIs. + */ + @Test + public void testRemove_two_DOIs_from_item_metadata() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + // add two DOIs. + Item item = newItem(context); + String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + + // remove one of it + provider.removeDOIFromObject(context, item, doi1); + + // assure that the right one was removed + DCValue[] metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + boolean foundDOI1 = false; + boolean foundDOI2 = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi1))) + { + foundDOI1 = true; + } + if (id.value.equals(DOI.DOIToExternalForm(doi2))) + { + foundDOI2 = true; + } + + } + assertFalse("Cannot remove DOI from item metadata.", foundDOI1); + assertTrue("Removed wrong DOI from item metadata.", foundDOI2); + + // remove the otherone as well. + provider.removeDOIFromObject(context, item, doi2); + + // check it + metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + foundDOI1 = false; + foundDOI2 = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi1))) + { + foundDOI1 = true; + } + if (id.value.equals(DOI.DOIToExternalForm(doi2))) + { + foundDOI2 = true; + } + + } + assertFalse("Cannot remove DOI from item metadata.", foundDOI1); + assertFalse("Cannot remove DOI from item metadata.", foundDOI2); + } + + @Test + public void testMintDOI() throws SQLException, AuthorizeException, IOException + { + Item item = newItem(context); + String doi = null; + try + { + // get a DOI: + doi = provider.mint(context, item); + } + catch(IdentifierException e) + { + e.printStackTrace(); + fail("Got an IdentifierException: " + e.getMessage()); + } + + assertNotNull("Minted DOI is null!", doi); + assertFalse("Minted DOI is empty!", doi.isEmpty()); + + try + { + DOI.formatIdentifier(doi); + } + catch (Exception e) + { + e.printStackTrace(); + fail("Minted an unrecognizable DOI: " + e.getMessage()); + } + } + + @Test + public void testMint_returns_existing_DOI() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, null, true); + + String retrievedDOI = provider.mint(context, item); + + assertNotNull("Minted DOI is null?!", retrievedDOI); + assertTrue("Mint did not returned an existing DOI!", doi.equals(retrievedDOI)); + } + + @Test + public void testReserve_DOI() + throws SQLException, SQLException, AuthorizeException, IOException, + IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, null, true); + + provider.reserve(context, item, doi); + + TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow); + + assertTrue("Reservation of DOI did not set the corret DOI status.", + DOIIdentifierProvider.TO_BE_RESERVERED.intValue() == doiRow.getIntColumn("status")); + } + + @Test + public void testRegister_unreserved_DOI() + throws SQLException, SQLException, AuthorizeException, IOException, + IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, null, true); + + provider.register(context, item, doi); + + TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow); + + assertTrue("Registration of DOI did not set the corret DOI status.", + DOIIdentifierProvider.TO_BE_REGISTERED.intValue() == doiRow.getIntColumn("status")); + } + + @Test + public void testRegister_reserved_DOI() + throws SQLException, SQLException, AuthorizeException, IOException, + IdentifierException + { + Item item = newItem(context); + String doi = this.createDOI(item, DOIIdentifierProvider.IS_RESERVED, true); + + provider.register(context, item, doi); + + TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow); + + assertTrue("Registration of DOI did not set the corret DOI status.", + DOIIdentifierProvider.TO_BE_REGISTERED.intValue() == doiRow.getIntColumn("status")); + } + + @Test + public void testCreate_and_Register_DOI() + throws SQLException, SQLException, AuthorizeException, IOException, + IdentifierException + { + Item item = newItem(context); + + String doi = provider.register(context, item); + + // we want the created DOI to be returned in the following format: + // doi:10.<prefix>/<suffix>. + String formated_doi = DOI.formatIdentifier(doi); + assertTrue("DOI was not in the expected format!", doi.equals(formated_doi)); + + TableRow doiRow = DatabaseManager.findByUnique(context, "Doi", "doi", + doi.substring(DOI.SCHEME.length())); + assertNotNull("Created DOI was not stored in database.", doiRow); + + assertTrue("Registration of DOI did not set the corret DOI status.", + DOIIdentifierProvider.TO_BE_REGISTERED.intValue() == doiRow.getIntColumn("status")); + } + + @Test + public void testDelete_specified_DOI() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + + // remove one of it + provider.delete(context, item, doi1); + + // assure that the right one was removed + DCValue[] metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + boolean foundDOI1 = false; + boolean foundDOI2 = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi1))) + { + foundDOI1 = true; + } + if (id.value.equals(DOI.DOIToExternalForm(doi2))) + { + foundDOI2 = true; + } + } + assertFalse("Cannot remove DOI from item metadata.", foundDOI1); + assertTrue("Removed wrong DOI from item metadata.", foundDOI2); + + TableRow doiRow1 = DatabaseManager.findByUnique(context, "Doi", "doi", + doi1.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow1); + assertTrue("Status of deleted DOI was not set correctly.", + DOIIdentifierProvider.TO_BE_DELETED.intValue() == doiRow1.getIntColumn("status")); + + TableRow doiRow2 = DatabaseManager.findByUnique(context, "Doi", "doi", + doi2.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow2); + assertTrue("While deleting a DOI the status of another changed.", + DOIIdentifierProvider.IS_REGISTERED.intValue() == doiRow2.getIntColumn("status")); + } + + @Test + public void testDelete_all_DOIs() + throws SQLException, AuthorizeException, IOException, IdentifierException + { + Item item = newItem(context); + String doi1 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + String doi2 = this.createDOI(item, DOIIdentifierProvider.IS_REGISTERED, true); + + // remove one of it + provider.delete(context, item); + + // assure that the right one was removed + DCValue[] metadata = item.getMetadata(DOIIdentifierProvider.MD_SCHEMA, + DOIIdentifierProvider.DOI_ELEMENT, + DOIIdentifierProvider.DOI_QUALIFIER, + null); + boolean foundDOI1 = false; + boolean foundDOI2 = false; + for (DCValue id : metadata) + { + if (id.value.equals(DOI.DOIToExternalForm(doi1))) + { + foundDOI1 = true; + } + if (id.value.equals(DOI.DOIToExternalForm(doi2))) + { + foundDOI2 = true; + } + } + assertFalse("Cannot remove DOI from item metadata.", foundDOI1); + assertFalse("Did not removed all DOIs from item metadata.", foundDOI2); + + TableRow doiRow1 = DatabaseManager.findByUnique(context, "Doi", "doi", + doi1.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow1); + assertTrue("Status of deleted DOI was not set correctly.", + DOIIdentifierProvider.TO_BE_DELETED.intValue() == doiRow1.getIntColumn("status")); + + TableRow doiRow2 = DatabaseManager.findByUnique(context, "Doi", "doi", + doi1.substring(DOI.SCHEME.length())); + assumeNotNull(doiRow2); + assertTrue("Did not set the status of all deleted DOIs as expected.", + DOIIdentifierProvider.TO_BE_DELETED.intValue() == doiRow2.getIntColumn("status")); + } + + + // test the following methods using the MockDOIConnector. + // updateMetadataOnline + // registerOnline + // reserveOnline + +} \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/identifier/EZIDIdentifierProviderTest.java b/dspace-api/src/test/java/org/dspace/identifier/EZIDIdentifierProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..54d71018fa6fb79a356a8d5ecc501f523a084a7f --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/EZIDIdentifierProviderTest.java @@ -0,0 +1,411 @@ +/** + * 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.identifier; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.UUID; +import org.dspace.AbstractUnitTest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.*; +import org.dspace.core.Context; +import org.dspace.kernel.ServiceManager; +import org.dspace.services.ConfigurationService; +import org.dspace.workflow.WorkflowItem; +import org.dspace.workflow.WorkflowManager; +import org.junit.*; +import static org.junit.Assert.*; + +/** + * + * @author mwood + */ +public class EZIDIdentifierProviderTest + extends AbstractUnitTest +{ + /** Name of the reserved EZID test authority */ + private static final String TEST_SHOULDER = "10.5072/FK2"; + + private static ServiceManager sm = null; + + private static ConfigurationService config = null; + + private static Community community; + + private static Collection collection; + + /** The most recently created test Item's ID */ + private static int itemID; + + public EZIDIdentifierProviderTest() + { + } + + private static void dumpMetadata(Item eyetem) + { + DCValue[] metadata = eyetem.getMetadata("dc", Item.ANY, Item.ANY, Item.ANY); + for (DCValue metadatum : metadata) + System.out.printf("Metadata: %s.%s.%s(%s) = %s\n", + metadatum.schema, + metadatum.element, + metadatum.qualifier, + metadatum.language, + metadatum.value); + } + + /** + * Create a fresh Item, installed in the repository. + * + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + private Item newItem(Context ctx) + throws SQLException, AuthorizeException, IOException + { + ctx.turnOffAuthorisationSystem(); + ctx.setCurrentUser(eperson); + + // Create an Item to play with + WorkspaceItem wsItem = WorkspaceItem.create(ctx, collection, false); + + // Get it from the workspace and set some metadata + Item item = wsItem.getItem(); + itemID = item.getID(); + + item.addMetadata("dc", "contributor", "author", null, "Author, A. N."); + item.addMetadata("dc", "title", null, null, "A Test Object"); + item.addMetadata("dc", "publisher", null, null, "DSpace Test Harness"); + item.update(); + + // I think we have to do this? + WorkflowItem wfItem = WorkflowManager.startWithoutNotify(ctx, wsItem); + WorkflowManager.advance(ctx, wfItem, ctx.getCurrentUser()); + wfItem.update(); + wfItem.deleteWrapper(); + + // Commit work, clean up + ctx.commit(); + ctx.restoreAuthSystemState(); + + return item; + } + + /* + @BeforeClass + public static void setUpClass() + throws Exception + { + Context ctx = new Context(); + ctx.turnOffAuthorisationSystem(); + + ctx.setCurrentUser(eperson); + + // Create an environment for our test objects to live in. + community = Community.create(null, ctx); + community.setMetadata("name", "A Test Community"); + community.update(); + + collection = community.createCollection(); + collection.setMetadata("name", "A Test Collection"); + collection.update(); + + ctx.complete(); + + // Find the usual kernel services + sm = kernelImpl.getServiceManager(); + + config = kernelImpl.getConfigurationService(); + + // Configure the service under test. + config.setProperty(EZIDIdentifierProvider.CFG_SHOULDER, TEST_SHOULDER); + config.setProperty(EZIDIdentifierProvider.CFG_USER, "apitest"); + config.setProperty(EZIDIdentifierProvider.CFG_PASSWORD, "apitest"); + + // Don't try to send mail. + config.setProperty("mail.server.disabled", "true"); + } + + @AfterClass + public static void tearDownClass() + throws Exception + { + System.out.print("Tearing down\n\n"); + Context ctx = new Context(); + dumpMetadata(Item.find(ctx, itemID)); + } + + @Before + public void setUp() + { + context.setCurrentUser(eperson); + context.turnOffAuthorisationSystem(); + } + + @After + public void tearDown() + { + context.restoreAuthSystemState(); + } + */ + + /** Dummy test. */ + @Test + public void testNothing() + { + System.out.println("dummy"); + } + + /** + * Test of supports method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testSupports_Class() + { + System.out.println("supports Class"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + Class<? extends Identifier> identifier = DOI.class; + boolean result = instance.supports(identifier); + assertTrue("DOI should be supported", result); + } + */ + + /** + * Test of supports method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testSupports_String() + { + System.out.println("supports String"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + String identifier = "doi:" + TEST_SHOULDER; + boolean result = instance.supports(identifier); + assertTrue(identifier + " should be supported", result); + } + */ + + /** + * Test of register method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testRegister_Context_DSpaceObject() + throws Exception + { + System.out.println("register Context, DSpaceObject"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject dso = newItem(context); + + String result = instance.register(context, dso); + assertTrue("Didn't get a DOI back", result.startsWith("doi:" + TEST_SHOULDER)); + System.out.println(" got identifier: " + result); + } + */ + + /** + * Test of register method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testRegister_3args() + throws SQLException, AuthorizeException, IOException + { + System.out.println("register 3"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject object = newItem(context); + + String identifier = UUID.randomUUID().toString(); + + instance.register(context, object, identifier); + } + */ + + /** + * Test of reserve method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testReserve() + throws Exception + { + System.out.println("reserve"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject dso = newItem(context); + String identifier = UUID.randomUUID().toString(); + instance.reserve(context, dso, identifier); + } + */ + + /** + * Test of mint method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testMint() + throws Exception + { + System.out.println("mint"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject dso = newItem(context); + String result = instance.mint(context, dso); + assertNotNull("Null returned", result); + } + */ + + /** + * Test of resolve method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testResolve() + throws Exception + { + System.out.println("resolve"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + String identifier = UUID.randomUUID().toString(); + DSpaceObject expResult = newItem(context); + instance.register(context, expResult, identifier); + + String[] attributes = null; + DSpaceObject result = instance.resolve(context, identifier, attributes); + assertEquals(expResult, result); + } + */ + + /** + * Test of lookup method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testLookup() + throws Exception + { + System.out.println("lookup"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + String identifier = UUID.randomUUID().toString(); + DSpaceObject object = newItem(context); + instance.register(context, object, identifier); + + String result = instance.lookup(context, object); + assertNotNull("Null returned", result); + } + */ + + /** + * Test of delete method, of class DataCiteIdentifierProvider. + */ + /* + @Test + public void testDelete_Context_DSpaceObject() + throws Exception + { + System.out.println("delete 2"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject dso = newItem(context); + + // Ensure that it has multiple DOIs (ooo, bad boy!) + String id1 = UUID.randomUUID().toString(); + String id2 = UUID.randomUUID().toString(); + instance.reserve(context, dso, id1); + instance.reserve(context, dso, id2); + + // Test deletion + try { + instance.delete(context, dso); + } catch (IdentifierException e) { + // Creation of the Item registers a "public" identifier, which can't be deleted. + assertEquals("Unexpected exception", "1 identifiers could not be deleted.", e.getMessage()); + } + + // See if those identifiers were really deleted. + ItemIterator found; + found = Item.findByMetadataField(context, + EZIDIdentifierProvider.MD_SCHEMA, + EZIDIdentifierProvider.DOI_ELEMENT, + EZIDIdentifierProvider.DOI_QUALIFIER, id1); + assertFalse("A test identifier is still present", found.hasNext()); + + found = Item.findByMetadataField(context, + EZIDIdentifierProvider.MD_SCHEMA, + EZIDIdentifierProvider.DOI_ELEMENT, + EZIDIdentifierProvider.DOI_QUALIFIER, id2); + assertFalse("A test identifier is still present", found.hasNext()); + } + */ + + /** + * Test of delete method, of class DataCiteIdentifierProvider. + */ + /* + @Test() + public void testDelete_3args() + throws Exception + { + System.out.println("delete 3"); + + EZIDIdentifierProvider instance + = (EZIDIdentifierProvider) + sm.getServicesByType(EZIDIdentifierProvider.class).get(0); + + DSpaceObject dso = newItem(context); + String identifier = UUID.randomUUID().toString(); + + // Set a known identifier on the object + instance.reserve(context, dso, identifier); + + // Test deletion + instance.delete(context, dso, identifier); + + // See if it is gone + ItemIterator found = Item.findByMetadataField(context, + EZIDIdentifierProvider.MD_SCHEMA, + EZIDIdentifierProvider.DOI_ELEMENT, + EZIDIdentifierProvider.DOI_QUALIFIER, identifier); + assertFalse("Test identifier is still present", found.hasNext()); + } + */ +} diff --git a/dspace-api/src/test/java/org/dspace/identifier/MockDOIConnector.java b/dspace-api/src/test/java/org/dspace/identifier/MockDOIConnector.java new file mode 100644 index 0000000000000000000000000000000000000000..db0f1d9fea62a48ec3eeef02ff96a7824564ab48 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/identifier/MockDOIConnector.java @@ -0,0 +1,171 @@ +/** + * 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.identifier; + +import java.util.HashMap; +import java.util.Map; +import mockit.Mock; +import mockit.MockUp; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.identifier.doi.DOIConnector; +import org.dspace.identifier.doi.DOIIdentifierException; + +/** + * + * @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de) + */ +public class MockDOIConnector +extends MockUp<DOIConnector> +implements org.dspace.identifier.doi.DOIConnector +{ + + public Map<String, Integer> reserved; + public Map<String, Integer> registered; + + public MockDOIConnector() + { + reserved = new HashMap<String, Integer>(); + registered = new HashMap<String, Integer>(); + } + + public void reset() + { + reserved.clear(); + registered.clear(); + } + + @Override + @Mock + public boolean isDOIReserved(Context context, String doi) + throws DOIIdentifierException + { + return reserved.containsKey(doi); + } + + @Override + @Mock + public boolean isDOIReserved(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + if (null == doi) + { + throw new NullPointerException(); + } + Integer itemId = reserved.get(doi); + return (itemId != null && itemId.intValue() == dso.getID()) ? true : false; + } + + @Override + @Mock + public boolean isDOIRegistered(Context context, String doi) + throws DOIIdentifierException + { + return registered.containsKey(doi); + } + + @Override + @Mock + public boolean isDOIRegistered(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + if (null == doi) + { + throw new NullPointerException(); + } + Integer itemId = registered.get(doi); + return (itemId != null && itemId.intValue() == dso.getID()) ? true : false; + } + + @Override + @Mock + public void deleteDOI(Context context, String doi) + throws DOIIdentifierException + { + if (reserved.remove(doi) == null) + { + throw new DOIIdentifierException("Trying to delete a DOI that was " + + "never reserved!", DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + registered.remove(doi); + } + + @Override + @Mock + public void reserveDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + Integer itemId = reserved.get(doi); + if (null != itemId) + { + if (dso.getID() == itemId.intValue()) + { + return; + } + else + { + throw new DOIIdentifierException("Trying to reserve a DOI that " + + "is reserved for another object.", + DOIIdentifierException.MISMATCH); + } + } + reserved.put(doi, new Integer(dso.getID())); + } + + @Override + @Mock + public void registerDOI(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + if (!reserved.containsKey(doi)) + { + throw new DOIIdentifierException("Trying to register an unreserverd " + + "DOI.", DOIIdentifierException.RESERVE_FIRST); + } + + if (reserved.get(doi).intValue() != dso.getID()) + { + throw new DOIIdentifierException("Trying to register a DOI that is" + + " reserved for another item.", DOIIdentifierException.MISMATCH); + } + + if (registered.containsKey(doi)) + { + if (registered.get(doi).intValue() == dso.getID()) + { + return; + } + else + { + throw new DOIIdentifierException("Trying to register a DOI that " + + "is registered for another item.", + DOIIdentifierException.MISMATCH); + } + } + + registered.put(doi, new Integer(dso.getID())); + } + + @Override + @Mock + public void updateMetadata(Context context, DSpaceObject dso, String doi) + throws DOIIdentifierException + { + if (!reserved.containsKey(doi)) + { + throw new DOIIdentifierException("Trying to update a DOI that is not " + + "registered!", DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + if (reserved.get(doi).intValue() != dso.getID()) + { + throw new DOIIdentifierException("Trying to update metadata of an " + + "unreserved DOI.", DOIIdentifierException.DOI_DOES_NOT_EXIST); + } + } + +} \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java b/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..4257ac6525869a49bd015d68476d9e20d58c1715 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/statistics/util/DummyHttpServletRequest.java @@ -0,0 +1,578 @@ +/** + * 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.statistics.util; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletInputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + +/** + * A mock request for testing. + * + * @author mwood + */ +class DummyHttpServletRequest implements HttpServletRequest +{ + private String agent = null; + + private String address = null; + + private String remoteHost = null; + + public void setAgent(String agent) + { + this.agent = agent; + } + + public void setAddress(String address) + { + this.address = address; + } + + public void setRemoteHost(String host) + { + this.remoteHost = host; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getAuthType() + */ + @Override + public String getAuthType() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getContextPath() + */ + @Override + public String getContextPath() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getCookies() + */ + @Override + public Cookie[] getCookies() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getDateHeader(java.lang.String) + */ + @Override + public long getDateHeader(String arg0) + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) + */ + @Override + public String getHeader(String key) + { + if ("User-Agent".equals(key)) + { + return agent; + } + else + { + return null; + } + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getHeaderNames() + */ + @Override + public Enumeration getHeaderNames() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getHeaders(java.lang.String) + */ + @Override + public Enumeration getHeaders(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getIntHeader(java.lang.String) + */ + @Override + public int getIntHeader(String arg0) + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getMethod() + */ + @Override + public String getMethod() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getPathInfo() + */ + @Override + public String getPathInfo() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getPathTranslated() + */ + @Override + public String getPathTranslated() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getQueryString() + */ + @Override + public String getQueryString() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getRemoteUser() + */ + @Override + public String getRemoteUser() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getRequestURI() + */ + @Override + public String getRequestURI() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getRequestURL() + */ + @Override + public StringBuffer getRequestURL() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() + */ + @Override + public String getRequestedSessionId() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getServletPath() + */ + @Override + public String getServletPath() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getSession() + */ + @Override + public HttpSession getSession() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getSession(boolean) + */ + @Override + public HttpSession getSession(boolean arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#getUserPrincipal() + */ + @Override + public Principal getUserPrincipal() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromCookie() + */ + @Override + public boolean isRequestedSessionIdFromCookie() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromURL() + */ + @Override + public boolean isRequestedSessionIdFromURL() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdFromUrl() + */ + @Override + public boolean isRequestedSessionIdFromUrl() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() + */ + @Override + public boolean isRequestedSessionIdValid() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) + */ + @Override + public boolean isUserInRole(String arg0) + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getAttribute(java.lang.String) + */ + @Override + public Object getAttribute(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getAttributeNames() + */ + @Override + public Enumeration getAttributeNames() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getCharacterEncoding() + */ + @Override + public String getCharacterEncoding() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getContentLength() + */ + @Override + public int getContentLength() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getContentType() + */ + @Override + public String getContentType() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getInputStream() + */ + @Override + public ServletInputStream getInputStream() throws IOException + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getLocale() + */ + @Override + public Locale getLocale() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getLocales() + */ + @Override + public Enumeration getLocales() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getParameter(java.lang.String) + */ + @Override + public String getParameter(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getParameterMap() + */ + @Override + public Map getParameterMap() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getParameterNames() + */ + @Override + public Enumeration getParameterNames() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String) + */ + @Override + public String[] getParameterValues(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getProtocol() + */ + @Override + public String getProtocol() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getReader() + */ + @Override + public BufferedReader getReader() throws IOException + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getRealPath(java.lang.String) + */ + @Override + public String getRealPath(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getRemoteAddr() + */ + @Override + public String getRemoteAddr() + { + return address; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getRemoteHost() + */ + @Override + public String getRemoteHost() + { + return remoteHost; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) + */ + @Override + public RequestDispatcher getRequestDispatcher(String arg0) + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getScheme() + */ + @Override + public String getScheme() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getServerName() + */ + @Override + public String getServerName() + { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#getServerPort() + */ + @Override + public int getServerPort() + { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#isSecure() + */ + @Override + public boolean isSecure() + { + // TODO Auto-generated method stub + return false; + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) + */ + @Override + public void removeAttribute(String arg0) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#setAttribute(java.lang.String, java.lang.Object) + */ + @Override + public void setAttribute(String arg0, Object arg1) + { + throw new UnsupportedOperationException("Not supported yet."); + } + + /* (non-Javadoc) + * @see javax.servlet.ServletRequest#setCharacterEncoding(java.lang.String) + */ + @Override + public void setCharacterEncoding(String arg0) + throws UnsupportedEncodingException + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int getRemotePort() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getLocalName() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String getLocalAddr() + { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public int getLocalPort() + { + throw new UnsupportedOperationException("Not supported yet."); + } + +} diff --git a/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..95617720cdec033717e833abf7902aff56552f74 --- /dev/null +++ b/dspace-api/src/test/java/org/dspace/statistics/util/SpiderDetectorTest.java @@ -0,0 +1,170 @@ +/** + * 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.statistics.util; + +import mockit.Mock; +import mockit.MockClass; +import mockit.Mockit; +import org.dspace.statistics.SolrLogger; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * @author mwood + */ +public class SpiderDetectorTest +{ + private static final String NOT_A_BOT_ADDRESS = "192.168.0.1"; + + @BeforeClass + static public void beforeClass() + { + Mockit.setUpMocks(MockSolrLogger.class); // Don't test SolrLogger here + } + @AfterClass + + static public void afterClass() + { + Mockit.tearDownMocks(SolrLogger.class); + } + + /** + * Test method for {@link org.dspace.statistics.util.SpiderDetector#readPatterns(java.io.File)}. + */ + @Test + public void testReadPatterns() + { +// FIXME fail("Not yet implemented"); + } + + /** + * Test method for {@link org.dspace.statistics.util.SpiderDetector#getSpiderIpAddresses()}. + */ + @Test + public void testGetSpiderIpAddresses() + { +// FIXME fail("Not yet implemented"); + } + + /** + * Test method for {@link org.dspace.statistics.util.SpiderDetector#isSpider(javax.servlet.http.HttpServletRequest)}. + */ + @Test + public void testIsSpiderHttpServletRequest() + { + DummyHttpServletRequest req = new DummyHttpServletRequest(); + req.setAddress(NOT_A_BOT_ADDRESS); // avoid surprises + req.setRemoteHost("notabot.example.com"); // avoid surprises + req.setAgent("Firefox"); // avoid surprises + + String candidate; + + // Test agent patterns + req.setAgent("msnbot is watching you"); + assertTrue("'msnbot' did not match any pattern", SpiderDetector.isSpider(req)); + + req.setAgent("Firefox"); + assertFalse("'Firefox' matched a pattern", SpiderDetector.isSpider(req)); + + // Test IP patterns + candidate = "192.168.2.1"; + req.setAddress(candidate); + assertTrue(candidate + " did not match IP patterns", SpiderDetector.isSpider(req)); + + req.setAddress(NOT_A_BOT_ADDRESS); + assertFalse(NOT_A_BOT_ADDRESS + " matched IP patterns", SpiderDetector.isSpider(req)); + + // Test DNS patterns + candidate = "baiduspider-dspace-test.crawl.baidu.com"; + req.setRemoteHost(candidate); + assertTrue(candidate + " did not match DNS patterns", SpiderDetector.isSpider(req)); + + candidate = "wiki.dspace.org"; + req.setRemoteHost(candidate); + assertFalse(candidate + " matched DNS patterns", SpiderDetector.isSpider(req)); + } + + /** + * Test method for {@link org.dspace.statistics.util.SpiderDetector#isSpider(java.lang.String, java.lang.String, java.lang.String, java.lang.String)}. + */ + @Test + public void testIsSpiderStringStringStringString() + { + String candidate; + + // Test IP patterns + candidate = "192.168.2.1"; + assertTrue(candidate + " did not match IP patterns", + SpiderDetector.isSpider(candidate, null, null, null)); + + candidate = NOT_A_BOT_ADDRESS; + assertFalse(candidate + " matched IP patterns", + SpiderDetector.isSpider(candidate, null, null, null)); + + // Test DNS patterns + candidate = "baiduspider-dspace-test.crawl.baidu.com"; + assertTrue(candidate + " did not match DNS patterns", + SpiderDetector.isSpider(NOT_A_BOT_ADDRESS, null, candidate, null)); + + candidate = "wiki.dspace.org"; + assertFalse(candidate + " matched DNS patterns", + SpiderDetector.isSpider(NOT_A_BOT_ADDRESS, null, candidate, null)); + + // Test agent patterns + candidate = "msnbot is watching you"; + assertTrue("'" + candidate + "' did not match agent patterns", + SpiderDetector.isSpider(NOT_A_BOT_ADDRESS, null, null, candidate)); + + candidate = "Firefox"; + assertFalse("'" + candidate + "' matched agent patterns", + SpiderDetector.isSpider(NOT_A_BOT_ADDRESS, null, null, candidate)); + } + + /** + * Test method for {@link org.dspace.statistics.util.SpiderDetector#isSpider(java.lang.String)}. + */ + @Test + public void testIsSpiderString() + { + String candidate; + + candidate = "192.168.2.1"; + assertTrue(candidate + " did not match IP patterns", + SpiderDetector.isSpider(candidate, null, null, null)); + + candidate = NOT_A_BOT_ADDRESS; + assertFalse(candidate + " matched IP patterns", + SpiderDetector.isSpider(candidate, null, null, null)); + + } + + /** + * Dummy SolrLogger for testing. + * @author mwood + */ + @MockClass (realClass = org.dspace.statistics.SolrLogger.class) + static public class MockSolrLogger + { + @Mock + public void $init() {} + + @Mock + public void $clinit() {} + + @Mock + public boolean isUseProxies() + { + return false; + } + } +} 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/CollectionItemList.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/CollectionItemList.java new file mode 100644 index 0000000000000000000000000000000000000000..22f2b48307c4d2f97fef7ee88dee7986872ce7ae --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/CollectionItemList.java @@ -0,0 +1,137 @@ +/** + * 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.webui.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.content.Collection; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.plugin.CollectionHomeProcessor; +import org.dspace.plugin.PluginException; +import org.dspace.browse.BrowseEngine; +import org.dspace.browse.BrowseIndex; +import org.dspace.browse.BrowseInfo; +import org.dspace.browse.BrowserScope; +import org.dspace.browse.BrowseException; +import org.dspace.sort.SortException; +import org.dspace.sort.SortOption; + + +/** + * This class obtains item list of the given collection by + * implementing the CollectionHomeProcessor. + * + * @author Keiji Suzuki + * + */ +public class CollectionItemList implements CollectionHomeProcessor +{ + // the name of a browse index to display collection's items + private static String name = ConfigurationManager.getProperty("webui.collectionhome.browse-name"); + // the number of authors to display before trncating + private static final int etal = ConfigurationManager.getIntProperty("webui.browse.author-limit", -1); + // the number of items to display per page + private static final int perpage = ConfigurationManager.getIntProperty("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 + private static boolean useDateaccessioned = ConfigurationManager.getBooleanProperty("webui.collectionhome.use.dateaccessioned", true); + // the number of sort option "dateaccessioned" + private static int number = -1; + + static + { + if (name == null) + { + name = "title"; + } + + if (useDateaccessioned) + { + try + { + for (SortOption option : SortOption.getSortOptions()) + { + if ("dateaccessioned".equals(option.getName())) + { + number = option.getNumber(); + break; + } + } + } + catch (SortException e) + { + // does nothing + } + } + } + + /** + * blank constructor - does nothing. + * + */ + public CollectionItemList() + { + + } + + /* (non-Javadoc) + * @see org.dspace.plugin.CommunityHomeProcessor#process(org.dspace.core.Context, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.dspace.content.Community) + */ + public void process(Context context, HttpServletRequest request, HttpServletResponse response, Collection collection) + throws PluginException, AuthorizeException + { + int offset = UIUtil.getIntParameter(request, "offset"); + if (offset < 0) + { + offset = 0; + } + + try + { + BrowseIndex bi = BrowseIndex.getBrowseIndex(name); + if (bi == null || !"item".equals(bi.getDisplayType())) + { + request.setAttribute("show.items", Boolean.FALSE); + return; + } + + BrowserScope scope = new BrowserScope(context); + scope.setBrowseContainer(collection); + scope.setBrowseIndex(bi); + scope.setEtAl(etal); + scope.setOffset(offset); + scope.setResultsPerPage(perpage); + if (number != -1) + { + scope.setSortBy(number); + scope.setOrder(SortOption.DESCENDING); + } + BrowseEngine be = new BrowseEngine(context); + BrowseInfo binfo = be.browse(scope); + request.setAttribute("browse.info", binfo); + + if (binfo.hasResults()) + { + request.setAttribute("show.items", Boolean.TRUE); + } + else + { + request.setAttribute("show.items", Boolean.FALSE); + } + } + catch (BrowseException e) + { + request.setAttribute("show.items", Boolean.FALSE); + } + } +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSiteSubmissions.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSiteSubmissions.java new file mode 100644 index 0000000000000000000000000000000000000000..4af7472d27b6bf4b1121a56a520e9bcf955f5acd --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSiteSubmissions.java @@ -0,0 +1,56 @@ +/** + * 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.webui.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.plugin.SiteHomeProcessor; +import org.dspace.plugin.PluginException; + +/** + * This class obtains recent submissions to the site by + * implementing the SiteHomeProcessor. + * + * @author Keiji Suzuki + * + */ +public class RecentSiteSubmissions implements SiteHomeProcessor +{ + /** + * blank constructor - does nothing. + * + */ + public RecentSiteSubmissions() + { + + } + + /* (non-Javadoc) + * @see org.dspace.plugin.CommunityHomeProcessor#process(org.dspace.core.Context, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.dspace.content.Community) + */ + @Override + public void process(Context context, HttpServletRequest request, HttpServletResponse response) + throws PluginException, AuthorizeException + { + try + { + RecentSubmissionsManager rsm = new RecentSubmissionsManager(context); + RecentSubmissions recent = rsm.getRecentSubmissions(null); + request.setAttribute("recent.submissions", recent); + + } + catch (RecentSubmissionsException e) + { + throw new PluginException(e); + } + } +} 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/components/TopCommunitiesSiteProcessor.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/TopCommunitiesSiteProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..5b355a7a0234c66e2dd01fd66d4590e530c2ecb1 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/TopCommunitiesSiteProcessor.java @@ -0,0 +1,58 @@ +/** + * 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.webui.components; + +import java.sql.SQLException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Community; +import org.dspace.core.Context; +import org.dspace.plugin.PluginException; +import org.dspace.plugin.SiteHomeProcessor; + +/** + * This class add top communities object to the request attributes to use in + * the site home page implementing the SiteHomeProcessor. + * + * @author Andrea Bollini + * + */ +public class TopCommunitiesSiteProcessor implements SiteHomeProcessor +{ + + /** + * blank constructor - does nothing. + * + */ + public TopCommunitiesSiteProcessor() + { + + } + + @Override + public void process(Context context, HttpServletRequest request, + HttpServletResponse response) throws PluginException, + AuthorizeException + { + // Get the top communities to shows in the community list + Community[] communities; + try + { + communities = Community.findAllTop(context); + } + catch (SQLException e) + { + throw new PluginException(e.getMessage(), e); + } + request.setAttribute("communities", communities); + } + +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java new file mode 100644 index 0000000000000000000000000000000000000000..c8eda6e1e7693466e7e2d7894dd8a80f121a31ff --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/VersioningItemHome.java @@ -0,0 +1,128 @@ +/** + * 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.webui.components; + +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.dspace.app.webui.util.VersionUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; +import org.dspace.plugin.ItemHomeProcessor; +import org.dspace.plugin.PluginException; +import org.dspace.versioning.Version; +import org.dspace.versioning.VersionHistory; + +public class VersioningItemHome implements ItemHomeProcessor { + + /** log4j category */ + private static Logger log = Logger.getLogger(VersioningItemHome.class); + + @Override + public void process(Context context, HttpServletRequest request, + HttpServletResponse response, Item item) throws PluginException, + AuthorizeException { + boolean versioningEnabled = ConfigurationManager.getBooleanProperty( + "versioning", "enabled"); + boolean newVersionAvailable = false; + boolean showVersionWorkflowAvailable = false; + boolean hasVersionButton = false; + boolean hasVersionHistory = false; + + VersionHistory history = null; + List<Version> historyVersions = new ArrayList<Version>(); + String latestVersionHandle = null; + String latestVersionURL = null; + if (versioningEnabled) { + try { + if(item.canEdit()) { + if (VersionUtil.isLatest(context, item) && item.isArchived()) { + hasVersionButton = true; + } + } + } catch (SQLException e) { + throw new PluginException(e.getMessage()); + } + + if (VersionUtil.hasVersionHistory(context, item)) { + hasVersionHistory = true; + history = VersionUtil.retrieveVersionHistory(context, item); + for(Version versRow : history.getVersions()) { + + //Skip items currently in submission + try { + if(VersionUtil.isItemInSubmission(context, versRow.getItem())) + { + continue; + } + else { + historyVersions.add(versRow); + } + } catch (SQLException e) { + throw new PluginException(e.getMessage()); + } + } + } + + // Check if we have a history for the item + Version latestVersion; + try { + latestVersion = VersionUtil.checkLatestVersion(context, item); + } catch (SQLException e) { + throw new PluginException(e.getMessage()); + } + + if (latestVersion != null) { + if (latestVersion != null + && latestVersion.getItemID() != item.getID()) { + // We have a newer version + Item latestVersionItem = latestVersion.getItem(); + if (latestVersionItem.isArchived()) { + // Available, add a link for the user alerting him that + // a new version is available + newVersionAvailable = true; + try { + latestVersionURL = HandleManager.resolveToURL( + context, latestVersionItem.getHandle()); + } catch (SQLException e) { + throw new PluginException(e.getMessage()); + } + latestVersionHandle = latestVersionItem.getHandle(); + } else { + // We might be dealing with a workflow/workspace item + showVersionWorkflowAvailable = true; + } + } + } + } + + request.setAttribute("versioning.enabled", versioningEnabled); + request.setAttribute("versioning.hasversionbutton", hasVersionButton); + request.setAttribute("versioning.hasversionhistory", hasVersionHistory); + request.setAttribute("versioning.history", history); + request.setAttribute("versioning.historyversions", historyVersions); + request.setAttribute("versioning.newversionavailable", + newVersionAvailable); + request.setAttribute("versioning.showversionwfavailable", + showVersionWorkflowAvailable); + request.setAttribute("versioning.latestversionhandle", + latestVersionHandle); + request.setAttribute("versioning.latestversionurl", latestVersionURL); + + } + +} 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/handle/HandleJSONResolver.java b/dspace-jspui/src/main/java/org/dspace/app/webui/handle/HandleJSONResolver.java new file mode 100644 index 0000000000000000000000000000000000000000..141696833e60eaf1d66d6c9c35123c6162cd566c --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/handle/HandleJSONResolver.java @@ -0,0 +1,117 @@ +/** + * 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.webui.handle; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.webui.json.JSONRequest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; + +import com.google.gson.Gson; + +public class HandleJSONResolver extends JSONRequest +{ + private static final Logger log = Logger + .getLogger(HandleJSONResolver.class); + + public void doJSONRequest(Context context, HttpServletRequest request, + HttpServletResponse resp) throws AuthorizeException, IOException + { + String reqPath = request.getPathInfo().replaceFirst(getSubPath()+"/", ""); + // remove the first slash if present + if (reqPath.startsWith("/")) + { + reqPath = reqPath.substring(1); + } + + Gson gson = new Gson(); + String jsonString = ""; + + try + { + if (reqPath.startsWith("resolve/")) + { + String handle = reqPath.substring("resolve/".length()); + if (StringUtils.isBlank(handle)) + { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + String url = HandleManager.resolveToURL(context, handle); + // Only an array or an abject is valid JSON. A simple string + // isn't. An object always uses key value pairs, so we use an + // array. + if (url != null) + { + jsonString = gson.toJson(new String[] {url}); + } + else + { + jsonString = gson.toJson(null); + } + } + else if (reqPath.equals("listprefixes")) + { + List<String> prefixes = new ArrayList<String>(); + prefixes.add(HandleManager.getPrefix()); + String additionalPrefixes = ConfigurationManager + .getProperty("handle.additional.prefixes"); + if (StringUtils.isNotBlank(additionalPrefixes)) + { + for (String apref : additionalPrefixes.split(",")) + { + prefixes.add(apref.trim()); + } + } + jsonString = gson.toJson(prefixes); + } + else if (reqPath.startsWith("listhandles/")) + { + if (ConfigurationManager.getBooleanProperty( + "handle.hide.listhandles", true)) + { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + String prefix = reqPath.substring("listhandles/".length()); + if (StringUtils.isBlank(prefix)) + { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + List<String> handlelist = HandleManager.getHandlesForPrefix( + context, prefix); + jsonString = gson.toJson(handlelist); + } + else + { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + resp.getWriter().print(jsonString); + return; + } + catch (SQLException e) + { + log.error(e.getMessage(), e); + return; + } + } +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/json/SubmissionLookupJSONRequest.java b/dspace-jspui/src/main/java/org/dspace/app/webui/json/SubmissionLookupJSONRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..aa2aef617230b5562c3566cb943085ba579315d5 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/json/SubmissionLookupJSONRequest.java @@ -0,0 +1,430 @@ +/** + * 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.webui.json; + +import gr.ekt.bte.core.Record; +import gr.ekt.bte.core.TransformationEngine; +import gr.ekt.bte.core.TransformationSpec; +import gr.ekt.bte.exceptions.BadTransformationSpec; +import gr.ekt.bte.exceptions.MalformedSourceException; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.MissingResourceException; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.fileupload.FileItemFactory; +import org.apache.commons.fileupload.FileUploadException; +import org.apache.commons.fileupload.disk.DiskFileItemFactory; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.util.Streams; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +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.Utils; +import org.dspace.submit.lookup.MultipleSubmissionLookupDataLoader; +import org.dspace.submit.lookup.SubmissionLookupOutputGenerator; +import org.dspace.submit.lookup.SubmissionLookupService; +import org.dspace.submit.lookup.SubmissionLookupUtils; +import org.dspace.submit.util.ItemSubmissionLookupDTO; +import org.dspace.submit.util.SubmissionLookupDTO; +import org.dspace.utils.DSpace; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * @author Andrea Bollini + * @author Kostas Stamatis + * @author Luigi Andrea Pascarelli + * @author Panagiotis Koutsourakis + */ +public class SubmissionLookupJSONRequest extends JSONRequest +{ + + private SubmissionLookupService service = new DSpace().getServiceManager() + .getServiceByName(SubmissionLookupService.class.getName(), + SubmissionLookupService.class); + + private static Logger log = Logger + .getLogger(SubmissionLookupJSONRequest.class); + + @Override + public void doJSONRequest(Context context, HttpServletRequest req, + HttpServletResponse resp) throws AuthorizeException, IOException + { + Gson json = new Gson(); + String suuid = req.getParameter("s_uuid"); + SubmissionLookupDTO subDTO = service.getSubmissionLookupDTO(req, suuid); + // Check that we have a file upload request + boolean isMultipart = ServletFileUpload.isMultipartContent(req); + if ("identifiers".equalsIgnoreCase(req.getParameter("type"))) + { + Map<String, Set<String>> identifiers = new HashMap<String, Set<String>>(); + Enumeration e = req.getParameterNames(); + + while (e.hasMoreElements()) + { + String parameterName = (String) e.nextElement(); + String parameterValue = req.getParameter(parameterName); + + if (parameterName.startsWith("identifier_") + && StringUtils.isNotBlank(parameterValue)) + { + Set<String> set = new HashSet<String>(); + set.add(parameterValue); + identifiers.put( + parameterName.substring("identifier_".length()), + set); + } + } + + List<ItemSubmissionLookupDTO> result = new ArrayList<ItemSubmissionLookupDTO>(); + + TransformationEngine transformationEngine = service + .getPhase1TransformationEngine(); + if (transformationEngine != null) + { + MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) transformationEngine + .getDataLoader(); + dataLoader.setIdentifiers(identifiers); + + try + { + SubmissionLookupOutputGenerator outputGenerator = (SubmissionLookupOutputGenerator) transformationEngine + .getOutputGenerator(); + outputGenerator.setDtoList(new ArrayList<ItemSubmissionLookupDTO>()); + log.debug("BTE transformation is about to start!"); + transformationEngine.transform(new TransformationSpec()); + log.debug("BTE transformation finished!"); + result = outputGenerator.getDtoList(); + } + catch (BadTransformationSpec e1) + { + log.error(e1.getMessage(), e1); + } + catch (MalformedSourceException e1) + { + log.error(e1.getMessage(), e1); + } + } + + subDTO.setItems(result); + service.storeDTOs(req, suuid, subDTO); + List<Map<String, Object>> dto = getLightResultList(result); + JsonElement tree = json.toJsonTree(dto); + JsonObject jo = new JsonObject(); + jo.add("result", tree); + resp.getWriter().write(jo.toString()); + + } + else if ("search".equalsIgnoreCase(req.getParameter("type"))) + { + String title = req.getParameter("title"); + String author = req.getParameter("authors"); + int year = UIUtil.getIntParameter(req, "year"); + + Map<String, Set<String>> searchTerms = new HashMap<String, Set<String>>(); + Set<String> tmp1 = new HashSet<String>(); + tmp1.add(title); + Set<String> tmp2 = new HashSet<String>(); + tmp2.add(author); + Set<String> tmp3 = new HashSet<String>(); + tmp3.add(String.valueOf(year)); + searchTerms.put("title", tmp1); + searchTerms.put("authors", tmp2); + searchTerms.put("year", tmp3); + + List<ItemSubmissionLookupDTO> result = new ArrayList<ItemSubmissionLookupDTO>(); + + TransformationEngine transformationEngine = service + .getPhase1TransformationEngine(); + if (transformationEngine != null) + { + MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) transformationEngine + .getDataLoader(); + dataLoader.setSearchTerms(searchTerms); + + try + { + SubmissionLookupOutputGenerator outputGenerator = (SubmissionLookupOutputGenerator) transformationEngine + .getOutputGenerator(); + outputGenerator.setDtoList(new ArrayList<ItemSubmissionLookupDTO>()); + log.debug("BTE transformation is about to start!"); + transformationEngine.transform(new TransformationSpec()); + log.debug("BTE transformation finished!"); + result = outputGenerator.getDtoList(); + } + catch (BadTransformationSpec e1) + { + log.error(e1.getMessage(), e1); + } + catch (MalformedSourceException e1) + { + log.error(e1.getMessage(), e1); + } + } + + subDTO.setItems(result); + service.storeDTOs(req, suuid, subDTO); + List<Map<String, Object>> dto = getLightResultList(result); + JsonElement tree = json.toJsonTree(dto); + JsonObject jo = new JsonObject(); + jo.add("result", tree); + resp.getWriter().write(jo.toString()); + } + else if ("details".equalsIgnoreCase(req.getParameter("type"))) + { + String i_uuid = req.getParameter("i_uuid"); + Map<String, Object> dto = getDetails(subDTO.getLookupItem(i_uuid), + context); + JsonElement tree = json.toJsonTree(dto); + JsonObject jo = new JsonObject(); + jo.add("result", tree); + resp.getWriter().write(jo.toString()); + } + else if (isMultipart) + { + + // Create a factory for disk-based file items + FileItemFactory factory = new DiskFileItemFactory(); + + // Create a new file upload handler + ServletFileUpload upload = new ServletFileUpload(factory); + // Parse the request + Map<String, String> valueMap = new HashMap<String, String>(); + InputStream io = null; + + // Parse the request + List<FileItem> iter; + String filename = null; + try + { + iter = upload.parseRequest(req); + for (FileItem item : iter) + { + String name = item.getFieldName(); + InputStream stream = item.getInputStream(); + if (item.isFormField()) + { + String value = Streams.asString(stream); + valueMap.put(name, value); + } + else + { + io = stream; + } + } + } + catch (FileUploadException e) + { + throw new IOException(e); + } + + suuid = valueMap.get("s_uuid"); + subDTO = service.getSubmissionLookupDTO(req, suuid); + + List<ItemSubmissionLookupDTO> result = new ArrayList<ItemSubmissionLookupDTO>(); + + TransformationEngine transformationEngine = service + .getPhase1TransformationEngine(); + if (transformationEngine != null) + { + MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) transformationEngine + .getDataLoader(); + + String tempDir = (ConfigurationManager + .getProperty("upload.temp.dir") != null) ? ConfigurationManager + .getProperty("upload.temp.dir") : System + .getProperty("java.io.tmpdir"); + File uploadDir = new File(tempDir); + if (!uploadDir.exists()) { + if (!uploadDir.mkdir()) { + uploadDir = null; + } + } + File file = File.createTempFile("submissionlookup-loader", + ".temp", + uploadDir); + BufferedOutputStream out = new BufferedOutputStream( + new FileOutputStream(file)); + Utils.bufferedCopy(io, out); + dataLoader.setFile(file.getAbsolutePath(), + valueMap.get("provider_loader")); + + try + { + SubmissionLookupOutputGenerator outputGenerator = (SubmissionLookupOutputGenerator) transformationEngine + .getOutputGenerator(); + outputGenerator.setDtoList(new ArrayList<ItemSubmissionLookupDTO>()); + log.debug("BTE transformation is about to start!"); + transformationEngine.transform(new TransformationSpec()); + log.debug("BTE transformation finished!"); + result = outputGenerator.getDtoList(); + } + catch (BadTransformationSpec e1) + { + log.error(e1.getMessage(), e1); + } + catch (MalformedSourceException e1) + { + log.error(e1.getMessage(), e1); + } + finally + { + file.delete(); + } + } + subDTO.setItems(result); + service.storeDTOs(req, suuid, subDTO); + List<Map<String, Object>> dto = getLightResultList(result); + if (valueMap.containsKey("skip_loader")) + { + if (valueMap.get("skip_loader").equals("true")) + { + Map<String, Object> skip = new HashMap<String, Object>(); + skip.put("skip", Boolean.TRUE); + skip.put("uuid", valueMap.containsKey("s_uuid") ? suuid + : -1); + skip.put( + "collectionid", + valueMap.containsKey("select-collection-file") ? valueMap + .get("select-collection-file") : -1); + dto.add(skip); + } + } + JsonElement tree = json.toJsonTree(dto); + JsonObject jo = new JsonObject(); + jo.add("result", tree); + resp.setContentType("text/plain"); +// if you works in localhost mode and use IE10 to debug the feature uncomment the follow line +// resp.setHeader("Access-Control-Allow-Origin","*"); + resp.getWriter().write(jo.toString()); + } + } + + private Map<String, Object> getDetails(ItemSubmissionLookupDTO item, + Context context) + { + List<String> fieldOrder = getFieldOrder(); + Record totalData = item.getTotalPublication(service.getProviders()); + Set<String> availableFields = totalData.getFields(); + List<String[]> fieldsLabels = new ArrayList<String[]>(); + for (String f : fieldOrder) + { + if (availableFields.contains(f)) + { + try + { + if (totalData.getValues(f)!=null && totalData.getValues(f).size()>0) + fieldsLabels.add(new String[] {f, I18nUtil.getMessage("jsp.submission-lookup.detail."+ f, context) }); + } + catch (MissingResourceException e) + { + fieldsLabels.add(new String[] { f, f }); + } + } + } + Map<String, Object> data = new HashMap<String, Object>(); + String uuid = item.getUUID(); + + Record pub = item.getTotalPublication(service.getProviders()); + Map<String, List<String>> publication1 = new HashMap<String, List<String>>(); + for (String field : pub.getFields()) + { + publication1 + .put(field, SubmissionLookupUtils.getValues(pub, field)); + } + + data.put("uuid", uuid); + data.put("providers", item.getProviders()); + data.put("publication", publication1); + data.put("fieldsLabels", fieldsLabels); + return data; + } + + private List<String> getFieldOrder() + { + if (service.getDetailFields()!=null){ + return service.getDetailFields(); + } + + //Default values, in case the property is not set + List<String> defaultValues = new ArrayList<String>(); + defaultValues.add("title"); + defaultValues.add("authors"); + defaultValues.add("editors"); + defaultValues.add("translators"); + defaultValues.add("chairs"); + defaultValues.add("issued"); + defaultValues.add("abstract"); + defaultValues.add("doi"); + defaultValues.add("journal"); + defaultValues.add("volume"); + defaultValues.add("issue"); + defaultValues.add("publisher"); + defaultValues.add("jissn"); + defaultValues.add("pisbn"); + defaultValues.add("eisbn"); + defaultValues.add("arxivCategory"); + defaultValues.add("keywords"); + defaultValues.add("mesh"); + defaultValues.add("language"); + defaultValues.add("subtype"); + defaultValues.add("translators"); + + return defaultValues; + } + + private List<Map<String, Object>> getLightResultList( + List<ItemSubmissionLookupDTO> result) + { + List<Map<String, Object>> publications = new ArrayList<Map<String, Object>>(); + if (result != null && result.size() > 0) + { + for (ItemSubmissionLookupDTO item : result) + { + String uuid = item.getUUID(); + Record pub = item.getTotalPublication(service.getProviders()); + Map<String, Object> data = new HashMap<String, Object>(); + data.put("uuid", uuid); + data.put("providers", item.getProviders()); + data.put("title", + SubmissionLookupUtils.getFirstValue(pub, "title")); + data.put( + "authors", + pub.getValues("authors") != null ? StringUtils.join( + SubmissionLookupUtils.getValues(pub, "authors") + .iterator(), ", ") : ""); + data.put("issued", + SubmissionLookupUtils.getFirstValue(pub, "issued")); + + publications.add(data); + } + } + return publications; + } +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/json/UploadProgressJSON.java b/dspace-jspui/src/main/java/org/dspace/app/webui/json/UploadProgressJSON.java new file mode 100644 index 0000000000000000000000000000000000000000..5ebdd187ffbdb146416298d74dd58c96e0067318 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/json/UploadProgressJSON.java @@ -0,0 +1,62 @@ +/** + * 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.webui.json; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.dspace.app.webui.util.FileUploadListener; +import org.dspace.app.webui.util.FileUploadRequest; +import org.dspace.authorize.AuthorizeException; +import org.dspace.core.Context; + +import com.google.gson.Gson; + +public class UploadProgressJSON extends JSONRequest +{ + @Override + public void doJSONRequest(Context context, HttpServletRequest req, + HttpServletResponse resp) throws AuthorizeException, IOException + { + HttpSession session = req.getSession(false); + if (session == null) + { + return; + } + + FileUploadListener listner = (FileUploadListener) session + .getAttribute(FileUploadRequest.FILE_UPLOAD_LISTNER); + if (listner == null || listner.getContentLength() == 0) + { + return; + } + else + { + long contentLength = listner.getContentLength(); + UploadProgressDTO dto = new UploadProgressDTO(); + long bytesRead = listner.getBytesRead(); + dto.readBytes = bytesRead; + dto.totalBytes = contentLength; + Gson gson = new Gson(); + resp.getWriter().write(gson.toJson(dto)); + if (listner.isCompleted()) + { + session.removeAttribute(FileUploadRequest.FILE_UPLOAD_LISTNER); + } + } + + } +} + +class UploadProgressDTO { + long totalBytes; + long readBytes; +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java new file mode 100644 index 0000000000000000000000000000000000000000..baf7b8c0ebef492e80c432b787401896f5f0c33a --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/AccessSettingTag.java @@ -0,0 +1,391 @@ +/** + * 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.webui.jsptag; + +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.log4j.Logger; +import org.dspace.app.util.SubmissionInfo; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.eperson.Group; + +import java.util.ArrayList; +import java.util.List; +import java.io.IOException; +import java.sql.SQLException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.jstl.fmt.LocaleSupport; +import javax.servlet.jsp.tagext.TagSupport; + +/** + * Tag to display embargo settings + * + * @author Keiji Suzuki + * @version $Revision$ + */ +public class AccessSettingTag extends TagSupport +{ + /** log4j category */ + private static Logger log = Logger.getLogger(AccessSettingTag.class); + + /** is advanced form enabled? */ + private static final boolean advanced = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); + + /** Name of the restricted group */ + private static final String restrictedGroup = ConfigurationManager.getProperty("webui.submission.restrictstep.groups"); + + /** the SubmittionInfo */ + private transient SubmissionInfo subInfo = null; + + /** the target DSpaceObject */ + private transient DSpaceObject dso = null; + + /** the target ResourcePolicy */ + private transient ResourcePolicy rp = null; + + /** disable the radio button for open/embargo access */ + private boolean embargo = false; + + /** hide the embargo date and reason fields */ + private boolean hidden = false; + + /** add the policy button */ + private boolean addpolicy = false; + + + public AccessSettingTag() + { + super(); + } + + public int doStartTag() throws JspException + { + String legend = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.legend"); + String label_name = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.label_name"); + String label_group = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.label_group"); + String label_embargo = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.label_embargo"); + String label_date = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.label_date"); + String radio0 = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.radio0"); + String radio1 = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.radio1"); + String radio_help = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.radio_help"); + String label_reason = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.label_reason"); + String button_confirm = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.button_confirm"); + + String help_name = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.name_help"); + String help_reason = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.access-setting.reason_help"); + + JspWriter out = pageContext.getOut(); + StringBuffer sb = new StringBuffer(); + + try + { + HttpServletRequest hrq = (HttpServletRequest) pageContext.getRequest(); + Context context = UIUtil.obtainContext(hrq); + + // get startDate and reason of the resource policy of the target DSpaceObject + List<ResourcePolicy> policies = null; + if (!advanced && dso != null) + { + policies = AuthorizeManager.findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM); + } + else if (rp != null) + { + policies = new ArrayList<ResourcePolicy>(); + policies.add(rp); + } + + String name = ""; + int group_id = 0; + String startDate = ""; + String reason = ""; + String radio0Checked = " checked=\"checked\""; + String radio1Checked = ""; + String disabled = " disabled=\"disabled\""; + if (policies != null && policies.size() > 0) + { + ResourcePolicy rp = policies.get(0); + name = (rp.getRpName() == null ? "" : rp.getRpName()); + group_id = rp.getGroup().getID(); + startDate = (rp.getStartDate() != null ? DateFormatUtils.format(rp.getStartDate(), "yyyy-MM-dd") : ""); + reason = (rp.getRpDescription() == null ? "" : rp.getRpDescription()); + if (!startDate.equals("")) + { + radio0Checked = ""; + radio1Checked = " checked=\"checked\""; + disabled = ""; + } + } + + // if advanced embargo is disabled, embargo date and reason fields are always enabled + if (!advanced) { + disabled = ""; + } + + if (embargo) + { + // Name + sb.append("<div class=\"form-group\">"); + sb.append(label_name).append("\n"); + sb.append("<p class=\"help-block\">").append(help_name).append("</p>").append("\n"); + sb.append("<input class=\"form-control\" name=\"name\" id=\"policy_name\" type=\"text\" maxlength=\"30\" value=\"").append(name).append("\" />\n"); + sb.append("</div>"); + + // Group + sb.append("<div class=\"form-group\">"); + sb.append(label_group).append("\n"); + sb.append("<select class=\"form-control\" name=\"group_id\" id=\"select_group\">\n"); + + Group[] groups = getGroups(context, hrq, subInfo); + if (groups != null) + { + for (Group group : groups) + { + sb.append("<option value=\"").append(group.getID()).append("\""); + if (group_id == group.getID()) { + sb.append(" selected=\"selected\""); + } + sb.append(">").append(group.getName()).append("</option>\n"); + } + } + else + { + sb.append("<option value=\"0\" selected=\"selected\">Anonymous</option>\n"); + } + sb.append("</select>\n"); + sb.append("</div>"); + // Select open or embargo + sb.append(label_embargo).append("\n"); + sb.append("<div class=\"radio\">"); + sb.append("<label><input name=\"open_access_radios\" type=\"radio\" value=\"0\"").append(radio0Checked).append(" />").append(radio0).append("</label>\n"); + sb.append("</div>"); + sb.append("<div class=\"radio\">"); + sb.append("<label><input name=\"open_access_radios\" type=\"radio\" value=\"1\"").append(radio1Checked).append(" />").append(radio1).append("</label>\n"); + sb.append("</div>"); + + } + + // Embargo Date + if (hidden) + { + sb.append("<input name=\"embargo_until_date\" id=\"embargo_until_date_hidden\" type=\"hidden\" value=\"").append(startDate).append("\" />\n");; + sb.append("<input name=\"reason\" id=\"reason_hidden\" type=\"hidden\" value=\"").append(reason).append("\" />\n"); + } + else + { + sb.append("<div class=\"form-group col-md-12\">"); + sb.append("<div class=\"col-md-2\">"); + sb.append(label_date); + sb.append("</div>"); + sb.append("<div class=\"col-md-2\">"); + sb.append("<input class=\"form-control\" name=\"embargo_until_date\" id=\"embargo_until_date\" maxlength=\"10\" size=\"10\" type=\"text\" value=\"").append(startDate).append("\"").append(disabled).append(" />\n"); + sb.append("</div>"); + sb.append("<div class=\"col-md-8\">"); + sb.append("<span class=\"help-block\">"+radio_help+"</span>"); + sb.append("</div>"); + sb.append("</div>"); + // Reason + sb.append("<div class=\"form-group col-md-12\">"); + sb.append("<div class=\"col-md-12\">"); + sb.append(label_reason).append("\n"); + sb.append("</div>"); + sb.append("<div class=\"col-md-12\">"); + sb.append("<p class=\"help-block\">").append(help_reason).append("</p>").append("\n"); + sb.append("</div>"); + sb.append("<div class=\"col-md-12\">"); + sb.append("<textarea class=\"form-control\" name=\"reason\" id=\"reason\" cols=\"30\" rows=\"5\"").append(disabled).append(">").append(reason).append("</textarea>\n"); + sb.append("</div>"); + sb.append("</div>"); + } + + // Add policy button + if (addpolicy) + { + + sb.append("<input class=\"btn btn-success col-md-offset-5\" name=\"submit_add_policy\" type=\"submit\" value=\"").append(button_confirm).append("\" />\n"); + + } + + + out.println(sb.toString()); + } + catch (IOException ie) + { + throw new JspException(ie); + } + catch (SQLException e) + { + throw new JspException(e); + } + + return SKIP_BODY; + } + + /** + * Get the browseInfo + * + * @return the browseInfo + */ + public SubmissionInfo getSubInfo() + { + return subInfo; + } + + /** + * Set the browseInfo + * + * @param browseInfo + * the browseInfo + */ + public void setSubInfo(SubmissionInfo subInfo) + { + this.subInfo = subInfo; + } + + /** + * Get the dso + * + * @return the dso + */ + public DSpaceObject getDso() + { + return dso; + } + + /** + * Set the the dso + * + * @param the dso + * the dso + */ + public void setDso(DSpaceObject dso) + { + this.dso = dso; + } + + /** + * Get the rp + * + * @return the rp + */ + public ResourcePolicy getRp() + { + return rp; + } + + /** + * Set the the rp + * + * @param the rp + * the rp + */ + public void setRp(ResourcePolicy rp) + { + this.rp = rp; + } + + /** + * Get the display open/embargo setting radio flag + * + * @return radio + */ + public boolean getEmbargo() + { + return embargo; + } + + /** + * Set the display open/embargo setting radio flag + * + * @param embargo + * boolean + */ + public void setEmbargo(boolean embargo) + { + this.embargo = embargo; + } + + /** + * Get the hidden flag + * + * @return hidden + */ + public boolean getHidden() + { + return hidden; + } + + /** + * Set the hidden flag + * + * @param hidden + * boolean + */ + public void setHidden(boolean hidden) + { + this.hidden = hidden; + } + + /** + * Set the add_policy button flag + * + * @param addpolicy + * boolean + */ + public void setAddpolicy(boolean addpolicy) + { + this.addpolicy = addpolicy; + } + + /** + * Get the add_policy button flag + * + * @return addpolicy + */ + public boolean getAddpolicy() + { + return addpolicy; + } + + public void release() + { + dso = null; + subInfo = null; + rp = null; + embargo = false; + hidden = false; + addpolicy = false; + } + + private Group[] getGroups(Context context, HttpServletRequest request, SubmissionInfo subInfo) + throws SQLException + { + Group[] groups = null; + // retrieve groups + if (restrictedGroup != null) + { + Group uiGroup = Group.findByName(context, restrictedGroup); + if (uiGroup != null) + { + groups = uiGroup.getMemberGroups(); + } + } + + if (groups == null || groups.length == 0){ + groups = Group.findAll(context, Group.NAME); + } + + return groups; + } + +} 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/PoliciesListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java new file mode 100644 index 0000000000000000000000000000000000000000..6dee1f132e7370a0a37b7908d01811c16f5dd6fe --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/PoliciesListTag.java @@ -0,0 +1,156 @@ +/** + * 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.webui.jsptag; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +import javax.servlet.jsp.JspException; +import javax.servlet.jsp.JspWriter; +import javax.servlet.jsp.jstl.fmt.LocaleSupport; +import javax.servlet.jsp.tagext.TagSupport; + +import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.log4j.Logger; +import org.dspace.authorize.ResourcePolicy; + +/** + * Tag to display embargo settings + * + * @author Keiji Suzuki + * @version $Revision$ + */ +public class PoliciesListTag extends TagSupport +{ + /** log4j category */ + private static Logger log = Logger.getLogger(PoliciesListTag.class); + + /** Groups to make options list */ + private transient List<ResourcePolicy> policies = null; + private transient boolean showButton = true; + + public PoliciesListTag() + { + super(); + } + + public int doStartTag() throws JspException + { + String label_name = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.label_name"); + String label_action = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.label_action"); + String label_group = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.label_group"); + String label_sdate = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.label_sdate"); + String label_edate = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.label_edate"); + + String label_emptypolicies = LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.policies-list.no_policies"); + + JspWriter out = pageContext.getOut(); + StringBuffer sb = new StringBuffer(); + + try + { + if (policies != null && policies.size() > 0) + { + sb.append("<div class=\"table-responsive\">\n"); + sb.append("<table class=\"table\">\n"); + sb.append("<tr>\n"); + sb.append("<th class=\"accessHeadOdd\">").append(label_name).append("</th>\n"); + sb.append("<th class=\"accessHeadEven\">").append(label_action).append("</th>\n"); + sb.append("<th class=\"accessHeadOdd\">").append(label_group).append("</th>\n"); + sb.append("<th class=\"accessHeadEven\">").append(label_sdate).append("</th>\n"); + sb.append("<th class=\"accessHeadOdd\">").append(label_edate).append("</th>\n"); + if(showButton) + { + sb.append("<th class=\"accessButton\"> </th>\n"); + } + sb.append("</tr>\n"); + + String column1 = "Even"; + String column2 = "Odd"; + for (ResourcePolicy policy : policies) + { + column1 = (column1.equals("Even") ? "Odd" : "Even"); + column2 = (column2.equals("Even") ? "Odd" : "Even"); + String rpName = (policy.getRpName() == null ? "" : policy.getRpName()); + String startDate = (policy.getStartDate() == null ? "" : DateFormatUtils.format(policy.getStartDate(), "yyyy-MM-dd")); + String endDate = (policy.getEndDate() == null ? "" : DateFormatUtils.format(policy.getEndDate(), "yyyy-MM-dd")); + + + sb.append("<tr>\n"); + sb.append("<td class=\"access").append(column1).append("\">").append(rpName).append("</td>\n"); + sb.append("<td class=\"access").append(column2).append("\">").append(policy.getActionText()).append("</td>\n"); + sb.append("<td class=\"access").append(column1).append("\">").append(policy.getGroup().getName()).append("</td>\n"); + sb.append("<td class=\"access").append(column2).append("\">").append(startDate).append("</td>\n"); + sb.append("<td class=\"access").append(column1).append("\">").append(endDate).append("</td>\n"); + if(showButton) { + sb.append("<td class=\"accessButton\">\n"); + sb.append("<input class=\"btn btn-default\" name=\"submit_edit_edit_policies_").append(policy.getID()).append("\" type=\"submit\" value=\"Edit\" /> <input class=\"btn btn-danger\" name=\"submit_delete_edit_policies_").append(policy.getID()).append("\" type=\"submit\" value=\"Remove\" />\n"); + sb.append("</td>\n"); + } + sb.append("</tr>\n"); + } + sb.append("</table>\n"); + sb.append("</div>\n"); + } + else + { + sb.append("<div class=\"alert alert-warning\">").append(label_emptypolicies).append("</div>").append("\n"); + } + out.println(sb.toString()); + } + catch (IOException ie) + { + throw new JspException(ie); + } + catch (SQLException e) + { + throw new JspException(e); + } + + return SKIP_BODY; + } + + /** + * Get the policies to list + * + * @return the policies + */ + public List<ResourcePolicy> getPolicies() + { + return policies; + } + + /** + * Set the policies to list + * + * @param itemsIn + * the policies + */ + public void setPolicies(List<ResourcePolicy> policies) + { + this.policies = policies; + } + + + public void release() + { + policies = null; + } + + public boolean isShowButton() + { + return showButton; + } + + public void setShowButton(boolean showButton) + { + this.showButton = showButton; + } + +} 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/BatchMetadataImportServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/BatchMetadataImportServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..36f1784c12187c351ec59b227829e487dd986663 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/BatchMetadataImportServlet.java @@ -0,0 +1,174 @@ +/** + * 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.webui.servlet; + +import java.io.*; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException; +import org.apache.log4j.Logger; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.FileUploadRequest; +import org.dspace.app.itemimport.BTEBatchImportService; +import org.dspace.app.itemimport.ItemImport; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.core.*; +import org.dspace.utils.DSpace; +import org.elasticsearch.common.collect.Lists; + +/** + * Servlet to batch import metadata via the BTE + * + * @author Stuart Lewis + */ +public class BatchMetadataImportServlet extends DSpaceServlet +{ + /** log4j category */ + private static Logger log = Logger.getLogger(BatchMetadataImportServlet.class); + + /** + * Respond to a post request for metadata bulk importing via csv + * + * @param context a DSpace Context object + * @param request the HTTP request + * @param response the HTTP response + * + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void doDSPost(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + // First, see if we have a multipart request (uploading a metadata file) + String contentType = request.getContentType(); + if ((contentType != null) && (contentType.indexOf("multipart/form-data") != -1)) + { + String message = null; + + // Process the file uploaded + try { + // Wrap multipart request to get the submission info + FileUploadRequest wrapper = new FileUploadRequest(request); + File f = wrapper.getFile("file"); + + int colId = Integer.parseInt(wrapper.getParameter("collection")); + Collection collection = Collection.find(context, colId); + + String inputType = wrapper.getParameter("inputType"); + + try { + ItemImport.processUploadableImport(f, new Collection[]{collection}, inputType, context); + + request.setAttribute("has-error", "false"); + + } catch (Exception e) { + request.setAttribute("has-error", "true"); + message = e.getMessage(); + e.printStackTrace(); + } + } catch (FileSizeLimitExceededException e) { + request.setAttribute("has-error", "true"); + message = e.getMessage(); + e.printStackTrace(); + } catch (Exception e) { + request.setAttribute("has-error", "true"); + message = e.getMessage(); + e.printStackTrace(); + } + + //Get all the possible data loaders from the Spring configuration + BTEBatchImportService dls = new DSpace().getSingletonService(BTEBatchImportService.class); + List<String> inputTypes =dls.getFileDataLoaders(); + + request.setAttribute("input-types", inputTypes); + + //Get all collections + List<Collection> collections = null; + String colIdS = request.getParameter("colId"); + if (colIdS!=null){ + collections = new ArrayList<Collection>(); + collections.add(Collection.find(context, Integer.parseInt(colIdS))); + + } + else { + collections = Arrays.asList(Collection.findAll(context)); + } + + request.setAttribute("collections", collections); + + request.setAttribute("message", message); + + // Show the upload screen + JSPManager.showJSP(request, response, "/dspace-admin/batchmetadataimport.jsp"); + + } + else + { + request.setAttribute("has-error", "true"); + + // Show the upload screen + JSPManager.showJSP(request, response, "/dspace-admin/batchmetadataimport.jsp"); + } + } + + /** + * GET request is only ever used to show the upload form + * + * @param context + * a DSpace Context object + * @param request + * the HTTP request + * @param response + * the HTTP response + * + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void doDSGet(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + //Get all the possible data loaders from the Spring configuration + BTEBatchImportService dls = new DSpace().getSingletonService(BTEBatchImportService.class); + List<String> inputTypes = dls.getFileDataLoaders(); + request.setAttribute("input-types", inputTypes); + + //Get all collections + List<Collection> collections = null; + String colIdS = request.getParameter("colId"); + if (colIdS!=null){ + collections = new ArrayList<Collection>(); + collections.add(Collection.find(context, Integer.parseInt(colIdS))); + + } + else { + collections = Arrays.asList(Collection.findAll(context)); + } + + request.setAttribute("collections", collections); + + // Show the upload screen + JSPManager.showJSP(request, response, "/dspace-admin/batchmetadataimport.jsp"); + } + +} \ No newline at end of file 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/RequestItemServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/RequestItemServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..8d1c54832793b0d60b3b0571d4a8223599df30d3 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/RequestItemServlet.java @@ -0,0 +1,538 @@ +/** + * 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.webui.servlet; + +import java.io.IOException; +import java.sql.SQLException; +import java.text.MessageFormat; +import java.util.Date; + +import javax.mail.MessagingException; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.requestitem.RequestItemAuthor; +import org.dspace.app.requestitem.RequestItemAuthorExtractor; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.RequestItemManager; +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.DCValue; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +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.handle.HandleManager; +import org.dspace.storage.bitstore.BitstreamStorageManager; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.dspace.utils.DSpace; + +/** + * Servlet for generate a statistisc report + * + * @author Arnaldo Dantas + * @version $Revision: 1.0 $ + */ +public class RequestItemServlet extends DSpaceServlet +{ + /** log4j category */ + private static Logger log = Logger.getLogger(RequestItemServlet.class); + + /** The information get by form step */ + public static final int ENTER_FORM_PAGE = 1; + + /** The link by submmiter email step*/ + public static final int ENTER_TOKEN = 2; + + /** The link Aproved genarate letter step*/ + public static final int APROVE_TOKEN = 3; + + /* resume leter for request user*/ + public static final int RESUME_REQUEST = 4; + + /* resume leter for request dspace administrator*/ + public static final int RESUME_FREEACESS = 5; + + protected void doDSGet(Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + // First get the step + int step = UIUtil.getIntParameter(request, "step"); + + try + { + switch (step) + { + case ENTER_FORM_PAGE: + processForm(context, request, response); + break; + + case ENTER_TOKEN: + processToken(context, request, response); + break; + + case APROVE_TOKEN: + processLetter(context, request, response); + break; + + case RESUME_REQUEST: + processAttach(context, request, response); + break; + + case RESUME_FREEACESS: + processAdmin(context, request, response); + break; + + default: + processForm(context, request, response); + } + context.complete(); + } + catch (MessagingException e) + { + throw new RuntimeException(e.getMessage(), e); + } + } + + protected void doDSPost(Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + // Treat as a GET + doDSGet(context, request, response); + } + + private void processForm (Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + boolean showRequestCopy = false; + if ("all".equalsIgnoreCase(ConfigurationManager.getProperty("request.item.type")) || + ("logged".equalsIgnoreCase(ConfigurationManager.getProperty("request.item.type")) && + context.getCurrentUser() != null)) + { + showRequestCopy = true; + } + + if (!showRequestCopy) + { + throw new AuthorizeException("The request copy feature is disabled"); + } + + // handle + String handle = request.getParameter("handle"); + + String bitstream_id=request.getParameter("bitstream-id"); + + // Title + String title = null; + Item item = null; + if (StringUtils.isNotBlank(handle)) + { + item = (Item) HandleManager.resolveToObject(context, handle); + + } + if (item == null) + { + JSPManager.showInvalidIDError(request, response, handle, -1); + } + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) + { + title = titleDC[0].value; + } + else + { + title = I18nUtil.getMessage("jsp.general.untitled", context); + } + + // User email from context + String requesterEmail = request.getParameter("email"); + EPerson currentUser = context.getCurrentUser(); + String userName = null; + + if (currentUser != null) + { + requesterEmail = currentUser.getEmail(); + userName = currentUser.getFullName(); + } + + if (request.getParameter("submit") != null) + { + String reqname = request.getParameter("reqname"); + String coment = request.getParameter("coment"); + if (coment == null || coment.equals("")) + coment = ""; + boolean allfiles = "true".equals(request.getParameter("allfiles")); + + // Check all data is there + if (requesterEmail == null || requesterEmail.equals("") || + reqname == null || reqname.equals("")) + { + request.setAttribute("handle",handle); + request.setAttribute("bitstream-id", bitstream_id); + request.setAttribute("reqname", reqname); + request.setAttribute("email", requesterEmail); + request.setAttribute("coment", coment); + request.setAttribute("title", title); + request.setAttribute("allfiles", allfiles?"true":null); + + request.setAttribute("requestItem.problem", new Boolean(true)); + JSPManager.showJSP(request, response, "/requestItem/request-form.jsp"); + return; + } + + try + { + // All data is there, send the email + Email email = Email.getEmail(I18nUtil.getEmailFilename( + context.getCurrentLocale(), "request_item.author")); + + RequestItemAuthor author = new DSpace() + .getServiceManager() + .getServiceByName( + RequestItemAuthorExtractor.class.getName(), + RequestItemAuthorExtractor.class) + .getRequestItemAuthor(context, item); + + String authorEmail = author.getEmail(); + String authorName = author.getFullName(); + String emailRequest; + + if (authorEmail != null) { + emailRequest = authorEmail; + } else { + emailRequest = ConfigurationManager + .getProperty("mail.helpdesk"); + } + + if (emailRequest == null) { + emailRequest = ConfigurationManager + .getProperty("mail.admin"); + } + email.addRecipient(emailRequest); + + email.addArgument(reqname); + email.addArgument(requesterEmail); + email.addArgument(allfiles ? I18nUtil + .getMessage("itemRequest.all") : Bitstream.find( + context, Integer.parseInt(bitstream_id)).getName()); + email.addArgument(HandleManager.getCanonicalForm(item + .getHandle())); + email.addArgument(title); // request item title + email.addArgument(coment); // message + email.addArgument(RequestItemManager.getLinkTokenEmail(context, + bitstream_id, item.getID(), requesterEmail, reqname, + allfiles)); + + email.addArgument(authorName); // corresponding author name + email.addArgument(authorEmail); // corresponding author email + email.addArgument(ConfigurationManager + .getProperty("dspace.name")); + email.addArgument(ConfigurationManager + .getProperty("mail.helpdesk")); + email.setReplyTo(requesterEmail); + email.send(); + + log.info(LogManager.getHeader(context, + "sent_email_requestItem", + "submitter_id=" + requesterEmail + + ",bitstream_id="+bitstream_id + + ",requestEmail="+requesterEmail)); + + request.setAttribute("handle", handle); + JSPManager.showJSP(request, response, + "/requestItem/request-send.jsp"); + } + catch (MessagingException me) + { + log.warn(LogManager.getHeader(context, + "error_mailing_requestItem", + ""), me); + JSPManager.showInternalError(request, response); + } + } + else + { + // Display request copy form + log.info(LogManager.getHeader(context, + "show_requestItem_form", + "problem=false")); + request.setAttribute("handle", handle); + request.setAttribute("bitstream-id", bitstream_id); + request.setAttribute("email", requesterEmail); + request.setAttribute("reqname", userName); + request.setAttribute("title", title); + request.setAttribute("allfiles", "true"); + JSPManager.showJSP(request, response, "/requestItem/request-form.jsp"); + } + } + + + /* receive token + * get all request data by token + * send email to request user + */ + private void processToken (Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + // Token + String token = request.getParameter("token"); + + TableRow requestItem = RequestItemManager.getRequestbyToken( context, token); + // validate + if (requestItem != null) + { + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + String title = ""; + if (item != null) + { + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) + title = titleDC[0].value; + } + request.setAttribute("request-name", requestItem.getStringColumn("request_name")); + request.setAttribute("handle", item.getHandle()); + request.setAttribute("title", title); + + JSPManager.showJSP(request, response, + "/requestItem/request-information.jsp"); + }else{ + JSPManager.showInvalidIDError(request, response, token, -1); + } + + } + + /* + * receive approvation and generate a letter + * get all request data by token + * send email to request user + */ + private void processLetter(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException, MessagingException { + // Token + String token = request.getParameter("token"); + boolean yes = request.getParameter("submit_yes") != null; + boolean no = request.getParameter("submit_no") != null; + + // get token, get register, get email template, format email, get + // message to jsp + TableRow requestItem = RequestItemManager.getRequestbyToken(context, + token); + + if (requestItem != null && (yes || no)) { + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + String title = titleDC.length > 0 ? titleDC[0].value : I18nUtil + .getMessage("jsp.general.untitled", context); + + + EPerson submiter = item.getSubmitter(); + + Object[] args = new String[]{ + requestItem.getStringColumn("request_name"), + HandleManager.getCanonicalForm(item.getHandle()), // User + title, // request item title + submiter.getFullName(), // # submmiter name + submiter.getEmail() // # submmiter email + }; + + String subject = I18nUtil.getMessage("itemRequest.response.subject." + + (yes ? "approve" : "reject"), context); + String message = MessageFormat.format(I18nUtil.getMessage("itemRequest.response.body." + + (yes ? "approve" : "reject"), context), args); + + // page + request.setAttribute("response", yes); + request.setAttribute("subject", subject); + request.setAttribute("message", message); + JSPManager.showJSP(request, response, + "/requestItem/request-letter.jsp"); + } else { + JSPManager.showInvalidIDError(request, response, token, -1); + } + } + + /* + * receive token + * get all request data by token + * send email to request user + */ + private void processAttach (Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + // Token + String token = request.getParameter("token"); + + //buttom + boolean submit_next = (request.getParameter("submit_next") != null); + + if (submit_next) + { + TableRow requestItem = RequestItemManager.getRequestbyToken( context, token); + // validate + if (requestItem != null) + { + // Token + String subject = request.getParameter("subject"); + String message = request.getParameter("message"); + boolean accept = UIUtil.getBoolParameter(request, "accept_request"); + try + { + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + Email email = new Email(); + email.setSubject(subject); + email.setContent("{0}"); + email.addRecipient(requestItem.getStringColumn("request_email")); + email.addArgument(message); + + // add attach + if (accept) { + if (requestItem.getBooleanColumn("allfiles")) { + Bundle[] bundles = item.getBundles("ORIGINAL"); + for (int i = 0; i < bundles.length; i++) { + Bitstream[] bitstreams = bundles[i] + .getBitstreams(); + for (int k = 0; k < bitstreams.length; k++) { + if (!bitstreams[k].getFormat().isInternal() + && RequestItemManager.isRestricted( + context, bitstreams[k])) { + email.addAttachment( + BitstreamStorageManager + .retrieve( + context, + bitstreams[k] + .getID()), + bitstreams[k].getName(), + bitstreams[k].getFormat() + .getMIMEType()); + } + } + } + } else { + Bitstream bit = Bitstream.find(context, + requestItem.getIntColumn("bitstream_id")); + email.addAttachment(BitstreamStorageManager + .retrieve(context, requestItem + .getIntColumn("bitstream_id")), bit + .getName(), bit.getFormat().getMIMEType()); + } + } + email.send(); + + requestItem.setColumn("accept_request",accept); + requestItem.setColumn("decision_date",new Date()); + DatabaseManager.update(context, requestItem); + + log.info(LogManager.getHeader(context, + "sent_attach_requestItem", + "token=" + token)); + + JSPManager.showJSP(request, response, + "/requestItem/request-free-access.jsp"); + } + catch (MessagingException me) + { + log.warn(LogManager.getHeader(context, + "error_mailing_requestItem", + ""), me); + JSPManager.showInternalError(request, response); + } + } else + JSPManager.showInvalidIDError(request, response, null, -1); + } else { + processToken(context, request, response); + } + } + + /* + * receive approvation and generate a letter + * get all request data by token + * send email to request user + */ + private void processAdmin(Context context, + HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException, SQLException, AuthorizeException + { + // Token + String token = request.getParameter("token"); + boolean free = request.getParameter("submit_free") != null; + String name = request.getParameter("name"); + String mail = request.getParameter("email"); + // get token, get register, get email template, format email, get + // message to jsp + TableRow requestItem = RequestItemManager.getRequestbyToken(context, + token); + + if (requestItem != null && free) { + try { + Item item = Item.find(context, + requestItem.getIntColumn("item_id")); + + String emailRequest; + EPerson submiter = item.getSubmitter(); + if (submiter != null) { + emailRequest = submiter.getEmail(); + } else { + emailRequest = ConfigurationManager + .getProperty("mail.helpdesk"); + } + if (emailRequest == null) { + emailRequest = ConfigurationManager + .getProperty("mail.admin"); + } + Email email = Email.getEmail(I18nUtil.getEmailFilename( + context.getCurrentLocale(), "request_item.admin")); + email.addRecipient(emailRequest); + + email.addArgument(Bitstream.find(context, + requestItem.getIntColumn("bitstream_id")).getName()); + email.addArgument(HandleManager.getCanonicalForm(item + .getHandle())); + email.addArgument(requestItem.getStringColumn("token")); + email.addArgument(name); + email.addArgument(mail); + + email.send(); + + log.info(LogManager.getHeader(context, "sent_adm_requestItem", + "token=" + requestItem.getStringColumn("token") + + "item_id=" + item.getID())); + + JSPManager.showJSP(request, response, + "/requestItem/response-send.jsp"); + } catch (MessagingException me) { + log.warn(LogManager.getHeader(context, + "error_mailing_requestItem", ""), me); + JSPManager.showInternalError(request, response); + } + } else { + JSPManager.showInvalidIDError(request, response, token, -1); + } + } +} \ No newline at end of file diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SHERPAPublisherPolicyServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SHERPAPublisherPolicyServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..88a33f5bc39f43ded9e30341881c5ae66e4014dc --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SHERPAPublisherPolicyServlet.java @@ -0,0 +1,101 @@ +/** + * 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.webui.servlet; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +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.SHERPAJournal; +import org.dspace.app.sherpa.SHERPAPublisher; +import org.dspace.app.sherpa.SHERPAResponse; +import org.dspace.app.sherpa.submit.SHERPASubmitService; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.utils.DSpace; + +/** + * This servlet use the SHERPASubmitService to build an html page with the + * publisher policy for the journal referred in the specified Item + * + * @author Andrea Bollini + * + */ +public class SHERPAPublisherPolicyServlet extends DSpaceServlet +{ + private SHERPASubmitService sherpaSubmitService = new DSpace() + .getServiceManager().getServiceByName( + SHERPASubmitService.class.getCanonicalName(), + SHERPASubmitService.class); + + /** log4j logger */ + private static Logger log = Logger + .getLogger(SHERPAPublisherPolicyServlet.class); + + protected void doDSGet(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + int itemID = UIUtil.getIntParameter(request, "item_id"); + Item item = Item.find(context, itemID); + if (item == null) + { + return; + } + SHERPAResponse shresp = sherpaSubmitService.searchRelatedJournals( + context, item); + if (shresp.isError()) + { + request.setAttribute("error", new Boolean(true)); + } + else + { + List<SHERPAJournal> journals = shresp.getJournals(); + if (journals != null) + { + Object[][] results = new Object[journals.size()][]; + if (journals.size() > 0) + { + Iterator<SHERPAJournal> ijourn = journals.iterator(); + int idx = 0; + while (ijourn.hasNext()) + { + SHERPAJournal journ = ijourn.next(); + List<SHERPAPublisher> publishers = shresp + .getPublishers(); + results[idx] = new Object[] { + journ, + publishers != null && publishers.size() > 0 ? publishers + .get(0) : null }; + idx++; + } + } + + request.setAttribute("result", results); + } + } + // Simply forward to the plain form + JSPManager.showJSP(request, response, "/sherpa/sherpa-policy.jsp"); + } + + protected void doDSPost(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + } +} 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/VersionHistoryServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/VersionHistoryServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..d0b894ecdd2acc2c1d169886739bc938a3ab80ac --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/VersionHistoryServlet.java @@ -0,0 +1,189 @@ +/** + * 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.webui.servlet; + +import java.io.IOException; +import java.sql.SQLException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.app.webui.util.VersionUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.utils.DSpace; +import org.dspace.versioning.Version; +import org.dspace.versioning.VersionHistory; + +/** + * Servlet for handling the operations in the version history page + * + * @author Pascarelli Luigi Andrea + * @version $Revision$ + */ +public class VersionHistoryServlet extends DSpaceServlet +{ + + /** log4j category */ + private static Logger log = Logger.getLogger(VersionHistoryServlet.class); + + protected void doDSGet(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + Integer itemID = UIUtil.getIntParameter(request, "itemID"); + String versionID = request.getParameter("versionID"); + + Item item = Item.find(context, itemID); + + if (item == null) { + throw new IllegalArgumentException("Item is null"); + } + + if(!AuthorizeManager.isAdmin(context, + item.getOwningCollection())) + { + // Check if only administrators can view the item history + if (new DSpace().getConfigurationService().getPropertyAsType( + "versioning.item.history.view.admin", true)) + { + throw new AuthorizeException(); + } + + } + + // manage if versionID is not came by request + VersionHistory history = VersionUtil.retrieveVersionHistory(context, + item); + if (versionID == null || versionID.isEmpty()) + { + Version version = history.getVersion(item); + if (version != null) + { + versionID = String.valueOf(version.getVersionId()); + } + } + String submit = UIUtil.getSubmitButton(request, "submit"); + if (submit != null && submit.equals("submit_cancel")) + { + // Pressed the cancel button, redirect us to the item page + response.sendRedirect(request.getContextPath() + "/handle/" + + item.getHandle()); + context.complete(); + return; + } + else if (submit != null && submit.equals("submit_delete")) + { + String[] versionIDs = request.getParameterValues("remove"); + Integer result = doDeleteVersions(request, itemID, versionIDs); + if (result != null) + { + response.sendRedirect(request.getContextPath() + + "/tools/history?delete=true&itemID="+history.getLatestVersion().getItemID()); + } + else + { + // We have removed everything, redirect us to the home page ! + response.sendRedirect(request.getContextPath()); + } + context.complete(); + return; + + } + else if (submit != null && submit.equals("submit_restore")) + { + + doRestoreVersion(request, itemID, versionID); + } + else if (submit != null && submit.equals("submit_update")) + { + doUpdateVersion(request, itemID, versionID); + response.sendRedirect(request.getContextPath() + + "/tools/history?itemID=" + itemID + "&versionID=" + + versionID); + context.complete(); + return; + } + + request.setAttribute("item", item); + request.setAttribute("itemID", itemID); + request.setAttribute("versionID", versionID); + JSPManager.showJSP(request, response, "/tools/version-history.jsp"); + } + + protected void doDSPost(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + // If this is not overridden, we invoke the raw HttpServlet "doGet" to + // indicate that POST is not supported by this servlet. + doDSGet(UIUtil.obtainContext(request), request, response); + } + + /** + * Delete the given version(s) + * + * @throws IOException + * @throws AuthorizeException + * @throws SQLException + */ + private Integer doDeleteVersions(HttpServletRequest request, + Integer itemID, String... versionIDs) throws SQLException, + AuthorizeException, IOException + { + + return VersionUtil.processDeleteVersions(UIUtil.obtainContext(request), + itemID, versionIDs); + + } + + /** + * Restore the given version + * + * @throws IOException + * @throws AuthorizeException + * @throws SQLException + * @throws NumberFormatException + */ + private Integer doRestoreVersion(HttpServletRequest request, + Integer itemID, String versionID) throws NumberFormatException, + SQLException, AuthorizeException, IOException + { + + String summary = request.getParameter("summary"); + VersionUtil.processRestoreVersion(UIUtil.obtainContext(request), + Integer.parseInt(versionID), summary); + return itemID; + } + + /** + * Update the summary of the given version + * + * @throws IOException + * @throws AuthorizeException + * @throws SQLException + */ + private Integer doUpdateVersion(HttpServletRequest request, Integer itemID, + String versionID) throws SQLException, AuthorizeException, + IOException + { + + String summary = request.getParameter("summary"); + VersionUtil.processUpdateVersion(UIUtil.obtainContext(request), itemID, + summary); + return itemID; + + } + +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/VersionItemServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/VersionItemServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..9e6ab2f38690a6bf9f551a3ed7766fd5a79eb409 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/VersionItemServlet.java @@ -0,0 +1,84 @@ +/** + * 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.webui.servlet; + +import java.io.IOException; +import java.sql.SQLException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.app.webui.util.VersionUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Item; +import org.dspace.core.Context; + +/** + * Servlet to handling the versioning of the item + * + * @author Pascarelli Luigi Andrea + * @version $Revision$ + */ +public class VersionItemServlet extends DSpaceServlet +{ + + /** log4j category */ + private static Logger log = Logger.getLogger(VersionItemServlet.class); + + + protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + Integer itemID = UIUtil.getIntParameter(request,"itemID"); + Item item = Item.find(context,itemID); + String submit = UIUtil.getSubmitButton(request,"submit"); + if (submit!=null && submit.equals("submit")){ + request.setAttribute("itemID", itemID); + JSPManager.showJSP(request, response, + "/tools/version-summary.jsp"); + return; + } + + String summary = request.getParameter("summary"); + if (submit!=null && submit.equals("submit_version")){ + Integer wsid = VersionUtil.processCreateNewVersion(context, itemID, summary); + response.sendRedirect(request.getContextPath()+"/submit?resume=" + wsid); + context.complete(); + return; + } + else if (submit!=null && submit.equals("submit_update_version")){ + String versionID = request.getParameter("versionID"); + request.setAttribute("itemID", itemID); + request.setAttribute("versionID", versionID); + JSPManager.showJSP(request, response, + "/tools/version-update-summary.jsp"); + return; + } + + //Send us back to the item page if we cancel ! + response.sendRedirect(request.getContextPath() + "/handle/" + item.getHandle()); + context.complete(); + + } + + + protected void doDSPost(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + // If this is not overridden, we invoke the raw HttpServlet "doGet" to + // indicate that POST is not supported by this servlet. + doDSGet(UIUtil.obtainContext(request), request, response); + } + +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/CurateServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/CurateServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..70324e6eff4b135ec721e5bb662840fdcd40a56d --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/CurateServlet.java @@ -0,0 +1,440 @@ +/** + * 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.webui.servlet.admin; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.dspace.app.util.Util; +import org.dspace.app.webui.servlet.DSpaceServlet; +import org.dspace.app.webui.util.CurateTaskResult; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +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.Constants; +import org.dspace.core.Context; +import org.dspace.core.I18nUtil; +import org.dspace.curate.Curator; +import org.dspace.core.LogManager; +import org.dspace.handle.HandleManager; + +/** + * + * @author Keiji Suzuki + */ +public class CurateServlet extends DSpaceServlet +{ + // Name of queue used when tasks queued in Admin UI + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); + + // curation status codes in Admin UI: key=status code, value=localized name + private static final Map<String, String> statusMessages = new HashMap<String, String>(); + + // curation tasks to appear in admin UI: key=taskID, value=friendly name + private static Map<String, String> allTasks = new LinkedHashMap<String, String>(); + + // named groups which display together in admin UI: key=groupID, value=friendly group name + private static Map<String, String> taskGroups = new LinkedHashMap<String, String>(); + + // group membership: key=groupID, value=array of taskID + private static Map<String, String[]> groupedTasks = new LinkedHashMap<String, String[]>(); + + static + { + try + { + setStatusMessages(); + setAllTasks(); + setTaskGroups(); + setGroupedTasks(); + } + catch (Exception we) + { + // noop + } + } + + /** Logger */ + private static Logger log = Logger.getLogger(CurateServlet.class); + + protected void doDSGet(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + doDSPost(context, request, response); + } + + protected void doDSPost(Context context, HttpServletRequest request, + HttpServletResponse response) throws ServletException, IOException, + SQLException, AuthorizeException + { + String button = UIUtil.getSubmitButton(request, "submit"); + + // When task gropu is changed, no submit button is clicked. + // Reset the submit button to inform the original page. + if ("submit".equals(button)) + { + if (request.getParameter("community_id") != null) + { + button = "submit_community_select"; + } + else if (request.getParameter("collection_id") != null) + { + button = "submit_collection_select"; + } + else if (request.getParameter("item_id") != null) + { + button = "submit_item_select"; + } + else + { + button = "submit_main_select"; + } + } + + if (button.startsWith("submit_community_")) + { + Community community = Community.find(context, + UIUtil.getIntParameter(request, "community_id")); + request.setAttribute("community", community); + + if (!AuthorizeManager.isAdmin(context, community)) + { + throw new AuthorizeException("Only community admins are allowed to perform curation tasks"); + } + + if ("submit_community_curate".equals(button)) + { + processCurateObject(context, request, community.getHandle()); + } + else if ("submit_community_queue".equals(button)) + { + processQueueObject(context, request, community.getHandle()); + } + + showPage(request, response, "/tools/curate-community.jsp"); + } + else if (button.startsWith("submit_collection_")) + { + Collection collection = Collection.find(context, + UIUtil.getIntParameter(request, "collection_id")); + request.setAttribute("collection", collection); + + if (!AuthorizeManager.isAdmin(context, collection)) + { + throw new AuthorizeException("Only collection admins are allowed to perform curation tasks"); + } + + if ("submit_collection_curate".equals(button)) + { + processCurateObject(context, request, collection.getHandle()); + } + else if ("submit_collection_queue".equals(button)) + { + processQueueObject(context, request, collection.getHandle()); + } + + showPage(request, response, "/tools/curate-collection.jsp"); + } + else if (button.startsWith("submit_item_")) + { + Item item = Item.find(context, + UIUtil.getIntParameter(request, "item_id")); + request.setAttribute("item", item); + + if (!AuthorizeManager.isAdmin(context, item)) + { + throw new AuthorizeException("Only item admins are allowed to perform curation tasks"); + } + + if ("submit_item_curate".equals(button)) + { + processCurateObject(context, request, item.getHandle()); + } + else if ("submit_item_queue".equals(button)) + { + processQueueObject(context, request, item.getHandle()); + } + + showPage(request, response, "/tools/curate-item.jsp"); + } + else if (button.startsWith("submit_main_")) + { + String handle = request.getParameter("handle"); + if (handle != null) + { + if (handle.endsWith("/0")) + { + if (!AuthorizeManager.isAdmin(context)) + { + throw new AuthorizeException("Only system admins are allowed to perform curation tasks over the site"); + } + } + else + { + DSpaceObject dso = HandleManager.resolveToObject(context, handle); + if (!AuthorizeManager.isAdmin(context, dso)) + { + throw new AuthorizeException("Only object (hdl:"+handle+") admins are allowed to perform curation tasks"); + } + } + if ("submit_main_curate".equals(button)) + { + processCurateObject(context, request, handle); + } + else if ("submit_main_queue".equals(button)) + { + processQueueObject(context, request, handle); + } + else if ("submit_main_cancel".equals(button)) + { + handle = null; + } + request.setAttribute("handle", handle); + } + + showPage(request, response, "/dspace-admin/curate-main.jsp"); + } + else + { + log.warn(LogManager.getHeader(context, "integrity_error", UIUtil + .getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + } + + private void showPage(HttpServletRequest request, HttpServletResponse response, + String page) throws ServletException, IOException, + SQLException, AuthorizeException + { + String group = request.getParameter("select_curate_group"); + String groupOptions = getGroupSelectOptions(group); + String taskOptions = getTaskSelectOptions(group); + + request.setAttribute("curate_group_options", groupOptions); + request.setAttribute("curate_task_options", taskOptions); + JSPManager.showJSP(request, response, page); + } + + private void processCurateObject(Context context, HttpServletRequest request, String handle) + { + String task = request.getParameter("curate_task"); + Curator curator = getCurator(task); + boolean success = false; + try + { + curator.curate(context, handle); + success = true; + } + catch (Exception e) + { + curator.setResult(task, e.getMessage()); + } + + request.setAttribute("task_result", getCurateMessage(context, curator, task, handle, success)); + } + + private void processQueueObject(Context context, HttpServletRequest request, String handle) { + String task = request.getParameter("curate_task"); + Curator curator = getCurator(task); + boolean success = false; + try + { + curator.queue(context, handle, TASK_QUEUE_NAME); + success = true; + } + catch (Exception e) + { + // no-op (any error should be logged by the Curator itself) + } + + request.setAttribute("task_result", new CurateTaskResult("queue", getTaskName(task), handle, null, null, success)); + } + + private CurateTaskResult getCurateMessage(Context context, Curator curator, String task, String handle, boolean success) + { + String status = statusMessages.get(String.valueOf(curator.getStatus(task))); + if (status == null) + { + status = statusMessages.get("other"); + } + + String result = curator.getResult(task); + if (result == null) + { + result = I18nUtil.getMessage("org.dspace.app.webui.servlet.admin.CurationServlet.null-result", context); + } + + return new CurateTaskResult("perform", getTaskName(task), handle, status, result, success); + } + + private Curator getCurator(String task) + { + if (task != null && task.length() == 0) + { + task = null; + } + Curator curator = new Curator(); + curator.addTask(task); + curator.setInvoked(Curator.Invoked.INTERACTIVE); + return curator; + } + + private static void setStatusMessages() throws UnsupportedEncodingException + { + String statusCodes = ConfigurationManager.getProperty("curate", "ui.statusmessages"); + for (String property : statusCodes.split(",")) + { + String[] keyValuePair = property.split("="); + statusMessages.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), + URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); + } + } + + private static void setAllTasks() throws UnsupportedEncodingException + { + String properties = ConfigurationManager.getProperty("curate", "ui.tasknames"); + for (String property : properties.split(",")) + { + String[] keyValuePair = property.split("="); + allTasks.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), + URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); + } + } + + private static void setTaskGroups() throws UnsupportedEncodingException + { + String groups = ConfigurationManager.getProperty("curate", "ui.taskgroups"); + if (groups != null) + { + for (String property : groups.split(",")) + { + String[] keyValuePair = property.split("="); + taskGroups.put(URLDecoder.decode(keyValuePair[0].trim(), "UTF-8"), + URLDecoder.decode(keyValuePair[1].trim(), "UTF-8")); + } + } + } + + private static void setGroupedTasks() throws UnsupportedEncodingException + { + if (!taskGroups.isEmpty()) + { + Iterator<String> iterator = taskGroups.keySet().iterator(); + while (iterator.hasNext()) + { + String groupID = iterator.next(); + String memberList = ConfigurationManager.getProperty("curate", "ui.taskgroup" + "." + groupID); + String[] members = memberList.split(","); + groupedTasks.put(URLDecoder.decode(groupID, "UTF-8"), members); + } + } + } + + /** + * Get the string of html option elements for group selection + * + * @param group the short name / identifier for the group + * @return the string of the html option elements + * return "" if no group exists. + */ + private String getGroupSelectOptions(String group) + { + StringBuilder sb = new StringBuilder(); + Iterator<String> iterator = taskGroups.keySet().iterator(); + while (iterator.hasNext()) + { + String groupID = iterator.next(); + sb.append("<option"); + if (groupID.equals(group)) + { + sb.append(" selected=\"selected\""); + } + sb.append(" value=\"").append(groupID).append("\">") + .append(taskGroups.get(groupID)).append("</option>\n"); + } + return sb.toString(); + } + + /** + * Get the string of html option elements for task selection of the specified task group + * when no task group exists, made from all tasks + * + * @param group the short name / identifier for the group + * @return the string of the html option elements + */ + private static String getTaskSelectOptions(String group) + { + StringBuilder sb = new StringBuilder(); + if (groupedTasks.isEmpty()) + { + Iterator<String> iterator = allTasks.keySet().iterator(); + while (iterator.hasNext()) + { + String task = iterator.next(); + sb.append("<option value=\"").append(task).append("\">") + .append(allTasks.get(task)).append("</option>\n"); + } + } + else + { + if (group == null || "".equals(group)) + { + group = groupedTasks.keySet().iterator().next(); + } + + String[] members = groupedTasks.get(group); + if (members != null && members.length > 0) + { + for (String member : members) + { + Iterator<String> innerIterator = allTasks.keySet().iterator(); + while (innerIterator.hasNext()) + { + String taskID = innerIterator.next().trim(); + if (taskID.equals(member.trim())) + { + sb.append("<option value=\"").append(taskID).append("\">") + .append(allTasks.get(taskID)).append("</option>\n"); + } + } + } + } + } + return sb.toString(); + } + + /** + * Retrieve UI "friendly" Task Name for display to user + * + * @param taskID the short name / identifier for the task + * @return the User Friendly name for this task + */ + private String getTaskName(String taskID) + { + return allTasks.containsKey(taskID) ? allTasks.get(taskID) : taskID; + } + +} 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/PrivateItemsServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/PrivateItemsServlet.java new file mode 100644 index 0000000000000000000000000000000000000000..dded39dba7a295049acf4635efaf90265a8cb590 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/PrivateItemsServlet.java @@ -0,0 +1,160 @@ +/** + * 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.webui.servlet.admin; + +import java.io.IOException; +import java.io.PrintWriter; +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.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.app.webui.servlet.AbstractBrowserServlet; +import org.dspace.authorize.AuthorizeException; +import org.dspace.browse.*; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.core.LogManager; +import org.dspace.sort.SortOption; +import org.apache.log4j.Logger; + +/** + * Servlet for browsing through private items: + * + * @author Keiji Suzuki + * @version $Revision$ + */ +public class PrivateItemsServlet extends AbstractBrowserServlet +{ + + /** log4j category */ + private static Logger log = Logger.getLogger(PrivateItemsServlet.class); + + /** + * Do the usual DSpace GET method. You will notice that browse does not currently + * respond to POST requests. + */ + protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + try + { + // all browse requests currently come to GET. + BrowserScope scope = getBrowserScopeForRequest(context, request, response); + + // Check that we are doing an item browse + if (scope.getBrowseIndex() == null || scope.getBrowseIndex().isItemIndex()) + { + // And override the index in the scope with the private items + scope.setBrowseIndex(BrowseIndex.getPrivateBrowseIndex()); + } + else + { + showError(context, request, response); + } + + // execute browse request + processBrowse(context, scope, request, response); + } + catch (BrowseException be) + { + log.error("caught exception: ", be); + throw new ServletException(be); + } + } + + + /** + * Display the error page + * + * @param context + * @param request + * @param response + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void showError(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + request.setAttribute("useAdminLayout", "yes"); + + JSPManager.showInternalError(request, response); + } + + /** + * Display the No Results page + * + * @param context + * @param request + * @param response + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void showNoResultsPage(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + request.setAttribute("browsePrivate", "yes"); + + JSPManager.showJSP(request, response, "/browse/no-results.jsp"); + } + + /** + * Display the single page. This is the page which lists just the single values of a + * metadata browse, not individual items. Single values are links through to all the items + * that match that metadata value + * + * @param context + * @param request + * @param response + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void showSinglePage(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + // Show an error as this currently isn't supported + showError(context, request, response); + } + + /** + * Display a full item listing. + * + * @param context + * @param request + * @param response + * @throws ServletException + * @throws IOException + * @throws SQLException + * @throws AuthorizeException + */ + protected void showFullPage(Context context, HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException, SQLException, + AuthorizeException + { + request.setAttribute("browsePrivate", "yes"); + + JSPManager.showJSP(request, response, "/browse/full.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/JSPAccessStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPAccessStep.java new file mode 100644 index 0000000000000000000000000000000000000000..8d4974e94d60fcdf027a94ccf931f7afdd1e7103 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPAccessStep.java @@ -0,0 +1,205 @@ +/** + * 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.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.util.SubmissionInfo; +import org.dspace.app.webui.submit.JSPStep; +import org.dspace.app.webui.submit.JSPStepManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.submit.AbstractProcessingStep; +import org.dspace.submit.step.AccessStep; + +/** + * + * @author Keiji Suzuki + * @version $Revision$ + */ +public class JSPAccessStep extends JSPStep +{ + /** JSP which displays the step to the user * */ + private static final String DISPLAY_JSP = "/submit/access-step.jsp"; + + /** JSP which edits the selected resource policy to the user * */ + private static final String EDIT_POLICY_JSP = "/submit/edit-policy.jsp"; + + private static final String REVIEW_JSP = "/submit/review-policy.jsp"; + + private boolean advanced = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); + + /** log4j logger */ + private static Logger log = Logger.getLogger(JSPAccessStep.class); + + /** + * Do any pre-processing to determine which JSP (if any) is used to generate + * the UI for this step. This method should include the gathering and + * validating of all data required by the JSP. In addition, if the JSP + * requires any variable to passed to it on the Request, this method should + * set those variables. + * <P> + * If this step requires user interaction, then this method must call the + * JSP to display, using the "showJSP()" method of the JSPStepManager class. + * <P> + * If this step doesn't require user interaction OR you are solely using + * Manakin for your user interface, then this method may be left EMPTY, + * since all step processing should occur in the doProcessing() method. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + */ + public void doPreProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + throws ServletException, IOException, SQLException, + AuthorizeException + { + // Tell JSPStepManager class to load "access-step.jsp" + JSPStepManager.showJSP(request, response, subInfo, DISPLAY_JSP); + } + + /** + * Do any post-processing after the step's backend processing occurred (in + * the doProcessing() method). + * <P> + * It is this method's job to determine whether processing completed + * successfully, or display another JSP informing the users of any potential + * problems/errors. + * <P> + * If this step doesn't require user interaction OR you are solely using + * Manakin for your user interface, then this method may be left EMPTY, + * since all step processing should occur in the doProcessing() method. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + * @param status + * any status/errors reported by doProcessing() method + */ + public void doPostProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo, int status) + throws ServletException, IOException, SQLException, + AuthorizeException + { + String buttonPressed = UIUtil.getSubmitButton(request, + AbstractProcessingStep.NEXT_BUTTON); + + if (status == AccessStep.STATUS_EDIT_POLICY) + { + JSPStepManager.showJSP(request, response, subInfo, EDIT_POLICY_JSP); + } + else if (buttonPressed.equals(AccessStep.FORM_ACCESS_BUTTON_ADD) + || buttonPressed.startsWith("submit_delete_edit_policies_") + || buttonPressed.equals(AccessStep.FORM_EDIT_BUTTON_CANCEL) + || buttonPressed.equals(AccessStep.FORM_EDIT_BUTTON_SAVE) + || status > 0) + { + // Here's some sample error message processing! + if (status > 0 && status != AccessStep.STATUS_EDIT_POLICY) + { + request.setAttribute("error_id", Integer.valueOf(status)); + } + + // special processing for this error message + JSPStepManager.showJSP(request, response, subInfo, DISPLAY_JSP); + } + } + + /** + * Retrieves the number of pages that this "step" extends over. This method + * is used by the SubmissionController 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 + { + return 1; + } + + /** + * Return the URL path (e.g. /submit/review-metadata.jsp) of the JSP + * which will review the information that was gathered in this Step. + * <P> + * This Review JSP is loaded by the 'Verify' Step, in order to dynamically + * generate a submission verification page consisting of the information + * gathered in all the enabled submission steps. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + */ + public String getReviewJSP(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + { + + // Policies List + List<ResourcePolicy> rpolicies = new ArrayList<ResourcePolicy>(); + try + { + rpolicies = AuthorizeManager.findPoliciesByDSOAndType(context, subInfo.getSubmissionItem().getItem(), ResourcePolicy.TYPE_CUSTOM); + } + catch (SQLException e) + { + log.error(e.getMessage(), e); + } + + Item item = subInfo.getSubmissionItem().getItem(); + request.setAttribute("submission.item.isdiscoverable", item.isDiscoverable()); + request.setAttribute("submission.item.rpolicies", rpolicies); + request.setAttribute("advancedEmbargo", advanced); + return REVIEW_JSP; + } + +} 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/JSPStartSubmissionLookupStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java new file mode 100644 index 0000000000000000000000000000000000000000..b99f503c09203d73ecf7ece294eca12ab01110ee --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPStartSubmissionLookupStep.java @@ -0,0 +1,270 @@ +/** + * 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.webui.submit.step; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.dspace.app.util.SubmissionInfo; +import org.dspace.app.webui.submit.JSPStep; +import org.dspace.app.webui.submit.JSPStepManager; +import org.dspace.app.webui.util.JSPManager; +import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.submit.lookup.SubmissionLookupDataLoader; +import org.dspace.submit.lookup.SubmissionLookupService; +import org.dspace.submit.step.StartSubmissionLookupStep; +import org.dspace.utils.DSpace; + +/** + * Step which controls selecting an item from external database service to auto + * fill metadata for DSpace JSP-UI + * <P> + * This JSPStep class works with the SubmissionController servlet for the JSP-UI + * <P> + * The following methods are called in this order: + * <ul> + * <li>Call doPreProcessing() method</li> + * <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> + * <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 + * (for the new page).</li> + * <li>Once all pages are complete, control is forwarded back to the + * SubmissionController, and the next step is called.</li> + * </ul> + * + * @see org.dspace.app.webui.servlet.SubmissionController + * @see org.dspace.app.webui.submit.JSPStep + * @see org.dspace.submit.step.StartSubmissionLookupStep + * + * @author Andrea Bollini + * @version $Revision$ + */ +public class JSPStartSubmissionLookupStep extends JSPStep +{ + /** JSP which displays HTML for this Class * */ + private static final String START_LOOKUP_JSP = "/submit/start-lookup-submission.jsp"; + + /** log4j logger */ + private static Logger log = Logger + .getLogger(JSPStartSubmissionLookupStep.class); + + SubmissionLookupService slService = new DSpace().getServiceManager() + .getServiceByName(SubmissionLookupService.class.getCanonicalName(), + SubmissionLookupService.class); + + /** + * Do any pre-processing to determine which JSP (if any) is used to generate + * the UI for this step. This method should include the gathering and + * validating of all data required by the JSP. In addition, if the JSP + * requires any variable to passed to it on the Request, this method should + * set those variables. + * <P> + * If this step requires user interaction, then this method must call the + * JSP to display, using the "showJSP()" method of the JSPStepManager class. + * <P> + * If this step doesn't require user interaction OR you are solely using + * Manakin for your user interface, then this method may be left EMPTY, + * since all step processing should occur in the doProcessing() method. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + */ + public void doPreProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + throws ServletException, IOException, SQLException, + AuthorizeException + { + if (request.getAttribute("no.collection") == null + || !(Boolean) request.getAttribute("no.collection")) + { + request.setAttribute("s_uuid", UUID.randomUUID().toString()); + } + + /* + * Possible parameters from JSP: + * + * collection= <collection_id> - a collection that has already been + * selected (to use as preference! it is not the final choice!!!) + * + * collectionid = the FINAL chosed collection!!! + * + * With no parameters, this servlet prepares for display of the Select + * Collection JSP. + */ + int collectionID = UIUtil.getIntParameter(request, "collectionid"); + Collection col = null; + + if (collectionID != -1) + { + col = Collection.find(context, collectionID); + } + + // if we already have a valid collection, then we can forward directly + // to post-processing + if (col != null) + { + log.debug("Select Collection page skipped, since a Collection ID was already found. Collection ID=" + + collectionID); + } + else + { + // gather info for JSP page + Community com = UIUtil.getCommunityLocation(request); + + Collection[] collections; + + if (com != null) + { + // In a community. Show collections in that community only. + collections = Collection.findAuthorized(context, com, + Constants.ADD); + } + else + { + // Show all collections + collections = Collection.findAuthorized(context, null, + Constants.ADD); + } + + // save collections to request for JSP + request.setAttribute("collections", collections); + request.setAttribute("collectionID", collectionID); + + Map<String, List<String>> identifiers2providers = slService + .getProvidersIdentifiersMap(); + List<String> searchProviders = slService.getSearchProviders(); + List<String> fileProviders = slService.getFileProviders(); + request.setAttribute("identifiers2providers", identifiers2providers); + request.setAttribute("searchProviders", searchProviders); + request.setAttribute("fileLoaders", fileProviders); + request.setAttribute("identifiers", slService.getIdentifiers()); + // we need to load the select collection JSP + JSPStepManager + .showJSP(request, response, subInfo, START_LOOKUP_JSP); + } + } + + /** + * Do any post-processing after the step's backend processing occurred (in + * the doProcessing() method). + * <P> + * It is this method's job to determine whether processing completed + * successfully, or display another JSP informing the users of any potential + * problems/errors. + * <P> + * If this step doesn't require user interaction OR you are solely using + * Manakin for your user interface, then this method may be left EMPTY, + * since all step processing should occur in the doProcessing() method. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + * @param status + * any status/errors reported by doProcessing() method + */ + public void doPostProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo, int status) + throws ServletException, IOException, SQLException, + AuthorizeException + { + // if the user didn't select a collection, + // send him/her back to "select a collection" page + if (status == StartSubmissionLookupStep.STATUS_NO_COLLECTION) + { + // specify "no collection" error message should be displayed + request.setAttribute("no.collection", new Boolean(true)); + + // reload this page, by re-calling doPreProcessing() + doPreProcessing(context, request, response, subInfo); + } + else if (status == StartSubmissionLookupStep.STATUS_INVALID_COLLECTION) + { + JSPManager.showInvalidIDError(request, response, + request.getParameter("collectionid"), Constants.COLLECTION); + } + else if (status == StartSubmissionLookupStep.STATUS_NO_SUUID) + { + // specify "no suuid" error message should be displayed + request.setAttribute("no.suuid", new Boolean(true)); + + // reload this page, by re-calling doPreProcessing() + doPreProcessing(context, request, response, subInfo); + } + else if (status == StartSubmissionLookupStep.STATUS_SUBMISSION_EXPIRED) + { + // specify "no collection" error message should be displayed + request.setAttribute("expired", new Boolean(true)); + + // reload this page, by re-calling doPreProcessing() + doPreProcessing(context, request, response, subInfo); + } + else if (status != StartSubmissionLookupStep.STATUS_COMPLETE) + { + // specify "no suuid" error message should be displayed + request.setAttribute("no.suuid", new Boolean(true)); + + // reload this page, by re-calling doPreProcessing() + doPreProcessing(context, request, response, subInfo); + } + } + + /** + * Return the URL path (e.g. /submit/review-metadata.jsp) of the JSP which + * will review the information that was gathered in this Step. + * <P> + * This Review JSP is loaded by the 'Verify' Step, in order to dynamically + * generate a submission verification page consisting of the information + * gathered in all the enabled submission steps. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + */ + public String getReviewJSP(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + { + return NO_JSP; // at this time, you cannot review what collection you + // selected. + } +} 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/JSPUploadWithEmbargoStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java new file mode 100644 index 0000000000000000000000000000000000000000..ca98c87db903598c1119aa79befc40af3a4bdcdc --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadWithEmbargoStep.java @@ -0,0 +1,458 @@ +/** + * 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.webui.submit.step; + +import java.io.IOException; +import java.sql.SQLException; +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.util.DCInputsReader; +import org.dspace.app.util.DCInputsReaderException; +import org.dspace.app.util.SubmissionInfo; +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; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; +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.dspace.core.LogManager; +import org.dspace.submit.step.AccessStep; +import org.dspace.submit.step.UploadStep; +import org.dspace.submit.step.UploadWithEmbargoStep; + +import com.google.gson.Gson; + +/** + * Upload step with the advanced embargo fucntion for DSpace JSP-UI. Handles the pages + * that revolve around uploading files (and verifying a successful upload) for an item + * being submitted into DSpace. + * <P> + * This JSPStep class works with the SubmissionController servlet + * for the JSP-UI + * <P> + * The following methods are called in this order: + * <ul> + * <li>Call doPreProcessing() method</li> + * <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 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 + * (for the new page).</li> + * <li>Once all pages are complete, control is forwarded back to the + * SubmissionController, and the next step is called.</li> + * </ul> + * + * @see org.dspace.app.webui.servlet.SubmissionController + * @see org.dspace.app.webui.submit.JSPStep + * @see org.dspace.app.webui.submit.JSPUploadStep + * @see org.dspace.submit.step.UploadStep + * + * @author Tim Donohue + * @author Keiji Suzuki + * @version $Revision$ + */ +public class JSPUploadWithEmbargoStep extends JSPUploadStep +{ + /** JSP to set access policies of uploaded files * */ + private static final String ACCESS_POLICIES_JSP = "/submit/set-policies.jsp"; + + /** JSP to edit access policy of selected policy * */ + private static final String EDIT_POLICY_JSP = "/submit/edit-policy.jsp"; + + /** JSP to edit access policy of selected policy * */ + private static final String EDIT_BITSTREAM_ACCESS_JSP = "/submit/edit-bitstream-access.jsp"; + + /** log4j logger */ + private static Logger log = Logger.getLogger(JSPUploadWithEmbargoStep.class); + + /** + * Do any post-processing after the step's backend processing occurred (in + * the doProcessing() method). + * <P> + * It is this method's job to determine whether processing completed + * successfully, or display another JSP informing the users of any potential + * problems/errors. + * <P> + * If this step doesn't require user interaction OR you are solely using + * Manakin for your user interface, then this method may be left EMPTY, + * since all step processing should occur in the doProcessing() method. + * + * @param context + * current DSpace context + * @param request + * current servlet request object + * @param response + * current servlet response object + * @param subInfo + * submission info object + * @param status + * any status/errors reported by doProcessing() method + */ + public void doPostProcessing(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo, int status) + throws ServletException, IOException, SQLException, + AuthorizeException + { + String buttonPressed = UIUtil.getSubmitButton(request, UploadStep.NEXT_BUTTON); + + // 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)) + { + Bundle[] bundles = subInfo.getSubmissionItem().getItem() + .getBundles("ORIGINAL"); + + boolean fileAlreadyUploaded = false; + + for (Bundle bnd : bundles) + { + fileAlreadyUploaded = bnd.getBitstreams().length > 0; + if (fileAlreadyUploaded) + { + break; + } + } + + // if user already has uploaded at least one file + if (fileAlreadyUploaded) + { + // return to list of uploaded files + showUploadFileList(context, request, response, subInfo, true, + false); + } + + return; // return immediately, since we are skipping upload + } + + //If upload failed in JSPUI (just came from upload-error.jsp), user can retry the upload + if(buttonPressed.equalsIgnoreCase("submit_retry")) + { + showUploadPage(context, request, response, subInfo, false); + } + // + else if (status == UploadWithEmbargoStep.STATUS_EDIT_POLICIES) + { + showEditBitstreamAccess(context, request, response, subInfo); + } + // [Cancel] button is pressed at edit-policy page + else if (status == UploadWithEmbargoStep.STATUS_EDIT_COMPLETE) + { + showUploadPage(context, request, response, subInfo, false); + } + // + else if (status == AccessStep.STATUS_EDIT_POLICY) + { + showEditPolicy(context, request, response, subInfo); + } + + // ------------------------------ + // Check for Errors! + // ------------------------------ + // if an error or message was passed back, determine what to do! + if (status != UploadStep.STATUS_COMPLETE) + { + if (status == UploadStep.STATUS_INTEGRITY_ERROR) + { + // Some type of integrity error occurred + log.warn(LogManager.getHeader(context, "integrity_error", + UIUtil.getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + else if (status == UploadStep.STATUS_UPLOAD_ERROR || status == UploadStep.STATUS_NO_FILES_ERROR) + { + // There was a problem uploading the file! + + //First, check if we just removed our uploaded file + if(buttonPressed.startsWith("submit_remove_")) + { + //if file was just removed, go back to upload page + showUploadPage(context, request, response, subInfo, false); + } + else + { + // We need to show the file upload error page + if (subInfo != null) + { + try + { + Collection c = subInfo.getSubmissionItem().getCollection(); + DCInputsReader inputsReader = new DCInputsReader(); + request.setAttribute("submission.inputs", inputsReader + .getInputs(c.getHandle())); + } + catch (DCInputsReaderException e) + { + throw new ServletException(e); + } + + } + JSPStepManager.showJSP(request, response, subInfo, UPLOAD_ERROR_JSP); + } + } + else if (status == UploadStep.STATUS_VIRUS_CHECKER_UNAVAILABLE) + { + // We need to show the file upload error page + if (subInfo != null) + { + try + { + Collection c = subInfo.getSubmissionItem().getCollection(); + DCInputsReader inputsReader = new DCInputsReader(); + request.setAttribute("submission.inputs", inputsReader + .getInputs(c.getHandle())); + } + catch (DCInputsReaderException e) + { + throw new ServletException(e); + } + + } + JSPStepManager.showJSP(request, response, subInfo, VIRUS_CHECKER_ERROR_JSP); + } + else if (status == UploadStep.STATUS_CONTAINS_VIRUS) + { + // We need to show the file upload error page + if (subInfo != null) + { + try + { + Collection c = subInfo.getSubmissionItem().getCollection(); + DCInputsReader inputsReader = new DCInputsReader(); + request.setAttribute("submission.inputs", inputsReader + .getInputs(c.getHandle())); + } + catch (DCInputsReaderException e) + { + throw new ServletException(e); + } + + } + JSPStepManager.showJSP(request, response, subInfo, VIRUS_ERROR_JSP); + } + else if (status == UploadStep.STATUS_UNKNOWN_FORMAT) + { + // user uploaded a file where the format is unknown to DSpace + + // forward user to page to request the file format + showGetFileFormat(context, request, response, subInfo); + } + } + + // As long as there are no errors, clicking Next + // should immediately send them to the next step + if (status == UploadStep.STATUS_COMPLETE && buttonPressed.equals(UploadStep.NEXT_BUTTON)) + { + // just return, so user will continue on to next step! + return; + } + + // ------------------------------ + // Check for specific buttons + // ------------------------------ + if (buttonPressed.equals(UploadStep.SUBMIT_MORE_BUTTON)) + { + // Upload another file (i.e. show the Choose File jsp again) + showChooseFile(context, request, response, subInfo); + } + else if (buttonPressed.equals("submit_show_checksums")) + { + // Show the checksums + showUploadFileList(context, request, response, subInfo, false, true); + } + else if (buttonPressed.startsWith("submit_describe_")) + { + // Change the description of a bitstream + Bitstream bitstream; + + // Which bitstream does the user want to describe? + try + { + int id = Integer.parseInt(buttonPressed.substring(16)); + bitstream = Bitstream.find(context, id); + } + catch (NumberFormatException nfe) + { + bitstream = null; + } + + if (bitstream == null) + { + // Invalid or mangled bitstream ID + // throw an error and return immediately + log.warn(LogManager.getHeader(context, "integrity_error", + UIUtil.getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + + // save the bitstream + subInfo.setBitstream(bitstream); + + // load the change file description page + showFileDescription(context, request, response, subInfo); + } + else if (buttonPressed.startsWith("submit_format_")) + { + // A "format is wrong" button must have been pressed + Bitstream bitstream; + + // Which bitstream does the user want to describe? + try + { + int id = Integer.parseInt(buttonPressed.substring(14)); + bitstream = Bitstream.find(context, id); + } + catch (NumberFormatException nfe) + { + bitstream = null; + } + + if (bitstream == null) + { + // Invalid or mangled bitstream ID + // throw an error and return immediately + log.warn(LogManager.getHeader(context, "integrity_error", + UIUtil.getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + + subInfo.setBitstream(bitstream); + showGetFileFormat(context, request, response, subInfo); + } + else + { + // BY DEFAULT: just display either the first upload page or the + // upload file listing + String contentType = request.getContentType(); + boolean fileUpload = false; + + // if multipart form, then we just finished a file upload + if ((contentType != null) + && (contentType.indexOf("multipart/form-data") != -1)) + { + fileUpload = true; + } + + // show the appropriate upload page + // (based on if a file has just been uploaded or not) + showUploadPage(context, request, response, subInfo, fileUpload); + } + } + + /** + * Show the page which allows the user to edit bitstream access settings + * was just uploaded + * + * @param context + * context object + * @param request + * the request object + * @param response + * the response object + * @param subInfo + * the SubmissionInfo object + */ + private void showEditBitstreamAccess(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + throws SQLException, ServletException, IOException + { + if (subInfo == null || subInfo.getBitstream() == null) + { + // We have an integrity error, since we seem to have lost + // which bitstream was just uploaded + log.warn(LogManager.getHeader(context, "integrity_error", UIUtil + .getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + + // display choose file format JSP next + JSPStepManager.showJSP(request, response, subInfo, EDIT_BITSTREAM_ACCESS_JSP); + } + + /** + * Show the page which allows the user to edit the specific resource policy + * was just uploaded + * + * @param context + * context object + * @param request + * the request object + * @param response + * the response object + * @param subInfo + * the SubmissionInfo object + */ + private void showEditPolicy(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + throws SQLException, ServletException, IOException + { + if (subInfo == null || subInfo.getBitstream() == null) + { + // We have an integrity error, since we seem to have lost + // which bitstream was just uploaded + log.warn(LogManager.getHeader(context, "integrity_error", UIUtil + .getRequestLogInfo(request))); + JSPManager.showIntegrityError(request, response); + } + + // display choose file format JSP next + JSPStepManager.showJSP(request, response, subInfo, EDIT_POLICY_JSP); + } + + @Override + public String getReviewJSP(Context context, HttpServletRequest request, + HttpServletResponse response, SubmissionInfo subInfo) + { + request.setAttribute("submission.step.uploadwithembargo", true); + return super.getReviewJSP(context, request, response, subInfo); + } +} 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/CurateTaskResult.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/CurateTaskResult.java new file mode 100644 index 0000000000000000000000000000000000000000..c55259f98a608febcb7e268b7bf0a474b9050d81 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/CurateTaskResult.java @@ -0,0 +1,78 @@ +/** + * 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.webui.util; + +import org.dspace.core.ConfigurationManager; + +/** + * + * @author Keiji Suzuki + */ +public class CurateTaskResult +{ + /** the type of curation: "perform" or "queue" */ + private String type; + + /** the task identifier*/ + private String task; + + /** the handle of the dspace-object */ + private String handle; + + /** the status string */ + private String status; + + /** the result string */ + private String result; + + /** Is the curation success? */ + private boolean isSuccess = false; + + public CurateTaskResult(String type, String task, String handle, String status, String result, boolean isSuccess) + { + this.type = type; + this.task = task; + this.handle = handle; + this.status = status; + this.result = result; + this.isSuccess = isSuccess; + } + + public String getType() + { + return type; + } + + public String getTask() + { + return task; + } + + public String getStatus() + { + return status; + } + + public String getResult() + { + return result; + } + + public String getHandle() + { + return handle; + } + + public boolean isSuccess() + { + return isSuccess; + } + +} + + diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadListener.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadListener.java new file mode 100644 index 0000000000000000000000000000000000000000..09b4883547c6fdb7c62a726b12ac065fe088ee8e --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadListener.java @@ -0,0 +1,47 @@ +/** + * 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.webui.util; + +import org.apache.commons.fileupload.ProgressListener; + +public class FileUploadListener implements ProgressListener +{ + private volatile long bytesRead = 0L, contentLength = 0L, item = 0L; + + public FileUploadListener() + { + super(); + } + + public void update(long aBytesRead, long aContentLength, int anItem) + { + bytesRead = aBytesRead; + contentLength = aContentLength; + item = anItem; + } + + public long getBytesRead() + { + return bytesRead; + } + + public long getContentLength() + { + return contentLength; + } + + public long getItem() + { + return item; + } + + public boolean isCompleted() + { + return bytesRead == contentLength; + } +} 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/JSONUploadResponse.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/JSONUploadResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..610630296eafa965eea20dc7fe415c34b02b643d --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/JSONUploadResponse.java @@ -0,0 +1,57 @@ +/** + * 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.webui.util; + +import java.util.ArrayList; +import java.util.List; + +public class JSONUploadResponse +{ + List<JSONUploadFileStatus> files = new ArrayList<JSONUploadFileStatus>(); + + JSONFileSizeLimitExceeded fileSizeLimitExceeded; + + public void addUploadFileStatus(String name, int bitstreamID, + long size, String url, int status) + { + JSONUploadFileStatus uploadFileStatus = new JSONUploadFileStatus(); + uploadFileStatus.name = name; + uploadFileStatus.bitstreamID = bitstreamID; + uploadFileStatus.size = size; + uploadFileStatus.url = url; + uploadFileStatus.status = status; + files.add(uploadFileStatus); + } + + public void addUploadFileSizeLimitExceeded(long actualSize, + long permittedSize) + { + this.fileSizeLimitExceeded = new JSONFileSizeLimitExceeded(); + fileSizeLimitExceeded.actualSize = actualSize; + fileSizeLimitExceeded.permittedSize = permittedSize; + } +} + +class JSONUploadFileStatus +{ + String name; + + int bitstreamID; + + long size; + + String url; + + int status; +} + +class JSONFileSizeLimitExceeded +{ + long actualSize; + long permittedSize; +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/RequestItemManager.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/RequestItemManager.java new file mode 100644 index 0000000000000000000000000000000000000000..07bd8e67fd5080cff422391fa25c6339080cf1fa --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/RequestItemManager.java @@ -0,0 +1,152 @@ +/** + * 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/ + */ +/* + * RequestItemManager.java + * + * Created on 27 de Marco de 2006, 17:12 by Arnaldo Dantas + * + */ + +package org.dspace.app.webui.util; + +import java.sql.SQLException; +import java.util.Date; +import java.util.List; + +import org.apache.log4j.Logger; +import org.dspace.app.webui.servlet.RequestItemServlet; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.core.Utils; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; + +/** + * + * @author Arnaldo Dantas + */ +public class RequestItemManager { + + /** log4j log */ + private static Logger log = Logger.getLogger(RequestItemManager.class); + + /* tablerow of requestitem table*/ + TableRow requestitem; + + /** Creates a new instance of RequestItemManager */ + public RequestItemManager(){} + + /** + * 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 + * Account token + * @return The email address corresponding to token, or null. + */ + public static TableRow getRequestbyToken(Context context, String token) + throws SQLException + { + TableRow rd = DatabaseManager.findByUnique(context, "requestitem", + "token", token); + + if (rd == null) + { + return null; + } + + /* + * ignore the expiration date on tokens Date expires = + * rd.getDateColumn("expires"); if (expires != null) { if ((new + * java.util.Date()).after(expires)) return null; } + */ + return rd; + } + + /* + * + */ + protected static String getNewToken(Context context, int bitstreamId + , int itemID, String reqEmail, String reqName, boolean allfiles) throws SQLException + { + TableRow rd = DatabaseManager.create(context, "requestitem"); + rd.setColumn("token", Utils.generateHexKey()); + rd.setColumn("bitstream_id", bitstreamId); + rd.setColumn("item_id",itemID); + rd.setColumn("allfiles", allfiles); + rd.setColumn("request_email", reqEmail); + rd.setColumn("request_name", reqName); + rd.setColumnNull("accept_request"); + rd.setColumn("request_date", new Date()); + rd.setColumnNull("decision_date"); + rd.setColumnNull("expires"); + // don't set expiration date any more + //rd.setColumn("expires", getDefaultExpirationDate()); + DatabaseManager.update(context, rd); + + // This is a potential problem -- if we create the callback + // and then crash, registration will get SNAFU-ed. + // So FIRST leave some breadcrumbs + if (log.isDebugEnabled()) + { + log.debug("Created requestitem_token " + + rd.getIntColumn("requestitem_id") + + " with token " + rd.getStringColumn("token") + + "\""); + } + return rd.getStringColumn("token"); + + } + + /** + * Get the link to the author in RequestLink email. + * + * @param email + * The email address to mail to + * + * @exception SQLExeption + * + */ + public static String getLinkTokenEmail(Context context, String bitstreamId + , int itemID, String reqEmail, String reqName, boolean allfiles) + throws SQLException + { + String base = ConfigurationManager.getProperty("dspace.url"); + + String specialLink = (new StringBuffer()).append(base).append( + base.endsWith("/") ? "" : "/").append( + "request-item").append("?step=" + RequestItemServlet.ENTER_TOKEN) + .append("&token=") + .append(getNewToken(context, Integer.parseInt(bitstreamId), itemID, reqEmail, reqName, allfiles)) + .toString(); + + return specialLink; + } + + public static boolean isRestricted(Context context, DSpaceObject o) throws SQLException + { + List<ResourcePolicy> policies = AuthorizeManager + .getPoliciesActionFilter(context, o, Constants.READ); + for (ResourcePolicy rp : policies) + { + if (rp.isDateValid()) + { + return false; + } + } + return true; + } + + +} 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/VersionUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..cf3757145a9c8d4f3d8dff65edf9af93d96ded32 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/VersionUtil.java @@ -0,0 +1,387 @@ +/** + * 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.webui.util; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.DCValue; +import org.dspace.content.InProgressSubmission; +import org.dspace.content.Item; +import org.dspace.content.MetadataSchema; +import org.dspace.content.WorkspaceItem; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.utils.DSpace; +import org.dspace.versioning.Version; +import org.dspace.versioning.VersionHistory; +import org.dspace.versioning.VersioningService; +import org.dspace.workflow.WorkflowItem; + +/** + * Item level versioning feature utility method + * + * @author Luigi Andrea Pascarelli + * + */ +public class VersionUtil +{ + + /** + * Create a new version of the specified item, otherwise return null + * + * @param context + * The DSpace context + * @param itemID + * The id of the to-be-versioned item + * @param summary + * The motif of the versioning + * @return Integer + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + public static Integer processCreateNewVersion(Context context, int itemID, + String summary) throws SQLException, AuthorizeException, + IOException + { + + try + { + + Item item = Item.find(context, itemID); + + if (AuthorizeManager.authorizeActionBoolean(context, item, + Constants.WRITE) || item.canEdit()) + { + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + Version version = versioningService.createNewVersion(context, + itemID, summary); + WorkspaceItem wsi = WorkspaceItem.findByItem(context, + version.getItem()); + + context.commit(); + + return wsi.getID(); + + } + } + catch (Exception ex) + { + context.abort(); + throw new RuntimeException(ex); + } + return null; + } + + /** + * Modify latest version + * + * @param context + * The DSpace context + * @param itemID + * The id of the to-be-versioned item + * @param summary + * The motif of the versioning + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + public static void processUpdateVersion(Context context, int itemID, + String summary) throws SQLException, AuthorizeException, + IOException + { + + try + { + + Item item = Item.find(context, itemID); + + if (AuthorizeManager.authorizeActionBoolean(context, item, + Constants.WRITE)) + { + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + versioningService.updateVersion(context, itemID, summary); + + context.commit(); + } + } + catch (Exception ex) + { + if (context != null && context.isValid()) + { + context.abort(); + } + throw new RuntimeException(ex); + } + + } + + /** + * Restore a version + * + * @param versionID + * id of the version to restore + * @param context + * The DSpace context + * @param summary + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + public static void processRestoreVersion(Context context, int versionID, + String summary) throws SQLException, AuthorizeException, + IOException + { + + try + { + + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + versioningService.restoreVersion(context, versionID, summary); + + context.commit(); + + } + catch (Exception ex) + { + if (context != null && context.isValid()) + { + context.abort(); + } + throw new RuntimeException(ex); + } + + } + + /** + * Delete version(s) + * + * @param context + * The DSpace context + * @param versionIDs + * list of versionIDs to delete + * @param itemId + * + * @return latest version item id or null if all versions has been removed + * @throws SQLException + * @throws AuthorizeException + * @throws IOException + */ + public static Integer processDeleteVersions(Context context, int itemId, + String[] versionIDs) throws SQLException, AuthorizeException, + IOException + { + + try + { + + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + VersionHistory versionHistory = versioningService + .findVersionHistory(context, itemId); + + for (String id : versionIDs) + { + versioningService.removeVersion(context, Integer.parseInt(id)); + } + context.commit(); + + // Retrieve the latest version of our history (IF any is even + // present) + Version latestVersion = versionHistory.getLatestVersion(); + if (latestVersion == null) + { + return null; + } + else + { + return latestVersion.getItemID(); + } + + } + catch (Exception ex) + { + if (context != null && context.isValid()) + { + context.abort(); + } + throw new RuntimeException(ex); + } + + } + + /** + * Check if the item is the last version builded + * + * @param context + * @param item + * @return true or false + */ + public static boolean isLatest(Context context, Item item) + { + VersionHistory history = retrieveVersionHistory(context, item); + return (history == null || history.getLatestVersion().getItem().getID() == item + .getID()); + } + + /** + * Check if the item have a version history + * + * @param context + * @param item + * @return true or false + */ + public static boolean hasVersionHistory(Context context, Item item) + { + VersionHistory history = retrieveVersionHistory(context, item); + return (history != null); + } + + /** + * Return the latest version, if there isn't or the user not have permission + * then return null. + * + * @param context + * @param item + * @return the latest version of the item + * @throws SQLException + */ + public static Version checkLatestVersion(Context context, Item item) + throws SQLException + { + + VersionHistory history = retrieveVersionHistory(context, item); + + if (history != null) + { + List<Version> allVersions = history.getVersions(); + for (Version version : allVersions) + { + if (version.getItem().isArchived() + || AuthorizeManager.isAdmin(context, + item.getOwningCollection())) + { + // We have a newer version + return version; + } + } + } + + return null; + } + + /** + * Retrieve the version history of the item + * + * @param context + * @param item + * @return history + */ + public static VersionHistory retrieveVersionHistory(Context context, + Item item) + { + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + return versioningService.findVersionHistory(context, item.getID()); + } + + /** + * Check item if it is in workspace or workflow + * + * @param context + * @param item + * @return true if item is in workflow or workspace + * @throws SQLException + */ + public static boolean isItemInSubmission(Context context, Item item) + throws SQLException + { + WorkspaceItem workspaceItem = WorkspaceItem.findByItem(context, item); + InProgressSubmission workflowItem = WorkflowItem.findByItem(context, + item); + + return workspaceItem != null || workflowItem != null; + } + + /** + * Retrieve an array of string where in first position there is the path + * builded from the dc.identifier (e.g. //authority/path where path is + * /handle/123456789/1), in second position founded the value of + * dc.identifier + * + * @param item + * @param version + * @return array of string + */ + public static String[] addItemIdentifier(Item item, Version version) + { + String[] result = null; + String itemHandle = version.getItem().getHandle(); + + DCValue[] identifiers = version.getItem().getMetadata( + MetadataSchema.DC_SCHEMA, "identifier", null, Item.ANY); + String itemIdentifier = null; + if (identifiers != null && identifiers.length > 0) + { + itemIdentifier = identifiers[0].value; + } + + if (itemIdentifier != null) + { + result = new String[] { "/resource/" + itemIdentifier, + itemIdentifier }; + } + else + { + result = new String[] { "/handle/" + itemHandle, itemHandle }; + } + return result; + } + + /** + * Retrieve the summary for the version + * + * @param context + * @param stringVersionID + * @return + */ + public static String getSummary(Context context, String stringVersionID) + { + String result = ""; + + try + { + Integer versionID = Integer.parseInt(stringVersionID); + VersioningService versioningService = new DSpace() + .getSingletonService(VersioningService.class); + Version version = versioningService.getVersion(context, versionID); + if (version != null) + { + result = version.getSummary(); + } + + } + catch (Exception ex) + { + if (context != null && context.isValid()) + { + context.abort(); + } + throw new RuntimeException(ex); + } + + return result; + } +} 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/java/org/dspace/utils/DSpaceWebapp.java b/dspace-jspui/src/main/java/org/dspace/utils/DSpaceWebapp.java new file mode 100644 index 0000000000000000000000000000000000000000..33b5b7d039be6daaf65201956d65a72a23d99872 --- /dev/null +++ b/dspace-jspui/src/main/java/org/dspace/utils/DSpaceWebapp.java @@ -0,0 +1,31 @@ +/** + * 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.utils; + +import org.dspace.app.util.AbstractDSpaceWebapp; + +/** + * An MBean to identify this web application. + * + * @author mwood + */ +public class DSpaceWebapp + extends AbstractDSpaceWebapp +{ + public DSpaceWebapp() + { + super("JSPUI"); + } + + @Override + public boolean isUI() + { + return true; + } +} 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/batchmetadataimport.jsp b/dspace-jspui/src/main/webapp/dspace-admin/batchmetadataimport.jsp new file mode 100644 index 0000000000000000000000000000000000000000..e59a697de0051e8d485ff87219ac2fa36717fe41 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/batchmetadataimport.jsp @@ -0,0 +1,99 @@ +<%-- + + 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/ + +--%> +<%-- + - Form to upload a csv metadata file +--%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="java.util.List" %> +<%@ page import="org.dspace.content.Collection" %> + +<% + + List<String> inputTypes = (List<String>)request.getAttribute("input-types"); + List<Collection> collections = (List<Collection>)request.getAttribute("collections"); + String hasErrorS = (String)request.getAttribute("has-error"); + boolean hasError = (hasErrorS==null) ? true : (Boolean.parseBoolean((String)request.getAttribute("has-error"))); + + String message = (String)request.getAttribute("message"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.batchmetadataimport.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin" + nocache="true"> + + <h1><fmt:message key="jsp.dspace-admin.batchmetadataimport.title"/></h1> + +<% + if (hasErrorS == null){ + + } + else if (hasError && message!=null){ +%> + <%= message %> +<% + } + else if (hasError && message==null){ +%> + <div class="alert alert-warning"><fmt:message key="jsp.dspace-admin.batchmetadataimport.genericerror"/></div> +<% + } + else { +%> + <div class="alert alert-info"><fmt:message key="jsp.dspace-admin.batchmetadataimport.success"/></div> +<% + } +%> + + <form method="post" enctype="multipart/form-data" action=""> + + + <div class="form-group"> + <label for="file"><fmt:message key="jsp.dspace-admin.batchmetadataimport.selectfile"/></label> + <input class="form-control" type="file" size="40" name="file"/> + </div> + <div class="form-group"> + <label for="inputType"><fmt:message key="jsp.dspace-admin.batchmetadataimport.selectinputfile"/></label> + <select class="form-control" name="inputType"> + <% + for (String inputType : inputTypes){ +%> + <option value="<%= inputType %>"><%= inputType %></option> + <% + } + %> + </select> + </div> + <div class="form-group"> + <label for="collection"><fmt:message key="jsp.dspace-admin.batchmetadataimport.selectcollection"/></label> + <select class="form-control" name="collection"> + <% + for (Collection collection : collections){ +%> + <option value="<%= collection.getID() %>"><%= collection.getName() %></option> + <% + } + %> + </select> + </div> + + <input class="btn btn-success" type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.general.upload"/>" /> + + </form> + +</dspace:layout> \ No newline at end of file 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/curate-collection.jsp b/dspace-jspui/src/main/webapp/dspace-admin/curate-collection.jsp new file mode 100644 index 0000000000000000000000000000000000000000..280c831d3599467247c341fa83b21cff3a2fb448 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/curate-collection.jsp @@ -0,0 +1,96 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - collection - the collection + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Collection" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Collection collection = (Collection) request.getAttribute("collection"); + int collectionID = (collection != null ? collection.getID() : -1); + int communityID = (collection.getParentObject() != null ? collection.getParentObject().getID() : -1); + String title = (collection != null ? collection.getMetadata("name") : "Unknown Collection"); + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.curate.collection.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/dspace-admin/curate-message.jsp" %> + + <h1><fmt:message key="jsp.dspace-admin.curate.collection.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + + + <form action="<%=request.getContextPath()%>/dspace-admin/curate" method="post"> + +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-group.tag"/>:</label> + + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> + </div> +<% + } +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-task.tag"/>:</label> + + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + <div class="input-group"> + <input type="hidden" name="collection_id" value="<%= collectionID %>"/> + <input class="btn btn-default" type="submit" name="submit_collection_curate" value="<fmt:message key="jsp.dspace-admin.curate.perform.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_collection_queue" value="<fmt:message key="jsp.dspace-admin.curate.queue.button"/>" /> + </div> + </form> + <div class="input-group"> + <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="collection_id" value="<%= collectionID %>"/> + <input type="hidden" name="community_id" value="<%= communityID %>" /> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_EDIT_COLLECTION %>" /> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.dspace-admin.curate.return.collection.button"/>" /> + </form> + </div> +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/curate-community.jsp b/dspace-jspui/src/main/webapp/dspace-admin/curate-community.jsp new file mode 100644 index 0000000000000000000000000000000000000000..82a48ed1003a366408f149d5e9fabdd11df49de8 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/curate-community.jsp @@ -0,0 +1,93 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - community - the community + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Community" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Community community = (Community) request.getAttribute("community"); + int communityID = (community != null ? community.getID() : -1); + String title = (community != null ? community.getMetadata("name") : "Unknown Community"); + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.curate.community.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/dspace-admin/curate-message.jsp" %> + + <h1><fmt:message key="jsp.dspace-admin.curate.community.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + + <form action="<%=request.getContextPath()%>/dspace-admin/curate" method="post"> +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-group.tag"/>:</label> + + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> + </div> +<% + } +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-task.tag"/>:</label> + + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + + <div class="input-group"> + <input type="hidden" name="community_id" value="<%= communityID %>"/> + <input class="btn btn-default" type="submit" name="submit_community_curate" value="<fmt:message key="jsp.dspace-admin.curate.perform.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_community_queue" value="<fmt:message key="jsp.dspace-admin.curate.queue.button"/>" /> + </div> + </form> + + <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="community_id" value="<%= communityID %>"/> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_EDIT_COMMUNITY%>""/> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.dspace-admin.curate.return.community.button"/>" /> + </form> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/curate-item.jsp b/dspace-jspui/src/main/webapp/dspace-admin/curate-item.jsp new file mode 100644 index 0000000000000000000000000000000000000000..9713795d65b5d99549289b2e9489c365593c04af --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/curate-item.jsp @@ -0,0 +1,107 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - item - the item + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Item" %> +<%@ page import="org.dspace.content.DCValue" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Item item = (Item) request.getAttribute("item"); + int itemID = (item != null ? item.getID() : -1); + String title = "Unknown Item"; + if (item != null) + { + DCValue[] dcvs = item.getMetadata("dc.title"); + if (dcvs != null && dcvs.length > 0) + { + title = dcvs[0].value; + } + } + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.curate.item.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/dspace-admin/curate-message.jsp" %> + + <h1><fmt:message key="jsp.dspace-admin.curate.item.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + <div class="row container"> + <form action="<%=request.getContextPath()%>/dspace-admin/curate" method="post"> +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-group.tag"/>:</label> + + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> + </div> + +<% + } +%> + + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.select-task.tag"/>:</label> + + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + + <br/> + <div class="col-md-4 row pull-right"> + <input type="hidden" name="item_id" value="<%= itemID %>"/> + <input class="btn btn-warning col-md-6" type="submit" name="submit_item_queue" value="<fmt:message key="jsp.tools.curate.queue.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_item_curate" value="<fmt:message key="jsp.tools.curate.perform.button"/>" /> + </div> + + </form> + </div> + + <div class="row container"> + <form method="get" action="<%=request.getContextPath()%>/tools/edit-item"> + <input type="hidden" name="item_id" value="<%= itemID %>"/> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.dspace-admin.curate.return.item.button"/>"/> + </form> + </div> +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/curate-main.jsp b/dspace-jspui/src/main/webapp/dspace-admin/curate-main.jsp new file mode 100644 index 0000000000000000000000000000000000000000..6d9cb06a09d91b623ccb85a5fffca5b77ba15e27 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/curate-main.jsp @@ -0,0 +1,96 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - handle - handle of the DSpaceObject + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + String handle = (String) request.getAttribute("handle"); + if (handle == null) + { + handle = ""; + } + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout + style="submission" + titlekey="jsp.dspace-admin.curate.main.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/tools/curate-message.jsp" %> + +<form action="<%=request.getContextPath()%>/dspace-admin/curate" method="post"> + + <h1><fmt:message key="jsp.dspace-admin.curate.main.heading"/></h1> + + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.curate.main.info1"/>:</label> + <input class="form-control" type="text" name="handle" value="<%= handle %>" size="20"/> + <span class="col-md-10"><fmt:message key="jsp.dspace-admin.curate.main.info2"/></span> + </div> + + + +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.tools.curate.select-group.tag"/>:</label> + + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> + </div> +<% + } +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.tools.curate.select-task.tag"/>:</label> + + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + + <div class="input-group"> + <input type="hidden" name="handle" value="<%= handle %>"/> + <input class="btn btn-default" type="submit" name="submit_main_curate" value="<fmt:message key="jsp.tools.curate.perform.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_main_queue" value="<fmt:message key="jsp.tools.curate.queue.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_main_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> +</form> +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/curate-message.jsp b/dspace-jspui/src/main/webapp/dspace-admin/curate-message.jsp new file mode 100644 index 0000000000000000000000000000000000000000..be71b0563e14657e975e497c70aabd6bbd5c1e54 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/curate-message.jsp @@ -0,0 +1,82 @@ +<%-- + + 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/ + +--%> +<% + CurateTaskResult result = (CurateTaskResult) request.getAttribute("task_result"); + if (result != null) + { + String type = result.getType(); + boolean isSuccess = result.isSuccess(); + String resultClass = (isSuccess ? "success" : "danger"); +%> + <div class="alert alert-<%= resultClass %>"> + <b> + <fmt:message key="jsp.dspace-admin.curate.task.name"> + <fmt:param value="<%= result.getTask() %>"/> + </fmt:message> + </b> +<% + if ("perform".equals(type)) + { + if (isSuccess) + { +%> + <p class="task-result"><fmt:message key="jsp.dspace-admin.curate.perform.success"/></p> + <div class="task-message"> + <fmt:message key="jsp.dspace-admin.curate.perform.message.success"> + <fmt:param value="<%= result.getStatus() %>"/> + <fmt:param value="<%= result.getResult() %>"/> + </fmt:message> + </div> +<% + } + else + { +%> + <p class="task-result"><fmt:message key="jsp.dspace-admin.curate.perform.failure"/></p> + <div class="task-message"> + <fmt:message key="jsp.dspace-admin.curate.perform.message.success"> + <fmt:param value="<%= result.getResult() %>"/> + </fmt:message> + </div> +<% + } + } + else + { + if (isSuccess) + { +%> + <p class="task-result"><fmt:message key="jsp.dspace-admin.curate.queue.success"/></p> + <div class="task-message"> + <fmt:message key="jsp.dspace-admin.curate.queue.message.success"> + <fmt:param value="<%= result.getHandle() %>"/> + <fmt:param value="<%= TASK_QUEUE_NAME %>"/> + </fmt:message> + </div> +<% + } + else + { +%> + <p class="task-result"><fmt:message key="jsp.dspace-admin.curate.queue.failure"/></p> + <div class="task-message"> + <fmt:message key="jsp.dspace-admin.curate.queue.message.failure"> + <fmt:param value="<%= result.getHandle() %>"/> + <fmt:param value="<%= TASK_QUEUE_NAME %>"/> + </fmt:message> + </div> +<% + } + } +%> + </div> +<% + } +%> 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-loginas-error.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-loginas-error.jsp new file mode 100644 index 0000000000000000000000000000000000000000..e62b41095d2e8f7b48377225ca9ae2a7300fa29e --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-loginas-error.jsp @@ -0,0 +1,36 @@ +<%-- + + 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/ + +--%> +<%-- + - Page representing an eperson loginas error + + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-main.loginAs.authorize.title"> + + <%-- <h1>Authorization Required</h1> --%> + <h1><fmt:message key="jsp.dspace-admin.eperson-main.loginAs.authorize.title"/></h1> + + + <p><fmt:message key="jsp.dspace-admin.eperson-main.loginAs.authorize.errormsg"/></p> + + + <p align="center"> + <a href="<%= request.getContextPath() %>/dspace-admin/edit-epeople"><fmt:message key="jsp.dspace-admin.eperson-main.loginAs.backtoeditpeople" /></a> + </p> + +</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/eperson-resetpassword-error.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-resetpassword-error.jsp new file mode 100644 index 0000000000000000000000000000000000000000..346b612d6c2c05b56ec5684de853d4beca811790 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-resetpassword-error.jsp @@ -0,0 +1,40 @@ +<%-- + + 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/ + +--%> +<%-- + - Page representing an eperson reset password error + + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ page isErrorPage="true" %> +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-main.ResetPassword.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + + <h1><fmt:message key="jsp.dspace-admin.eperson-main.ResetPassword.head" /></h1> + + + <p><fmt:message key="jsp.dspace-admin.eperson-main.ResetPassword-error.errormsg"/></p> + + + <p align="center"> + <a href="<%= request.getContextPath() %>/dspace-admin/edit-epeople"><fmt:message key="jsp.dspace-admin.eperson-main.ResetPassword.returntoedit" /></a> + </p> + +</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/supervise-no-workspaceitem.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-no-workspaceitem.jsp new file mode 100644 index 0000000000000000000000000000000000000000..3ce73e6e40d2afdf794d484465b0ec3a02582ea0 --- /dev/null +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-no-workspaceitem.jsp @@ -0,0 +1,38 @@ +<%-- + + 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 page displays an error message when no WorkspaceItem exists or + - the administrator does not select a WorkspaceItem + --%> + +<% request.setAttribute("LanguageSwitch", "hide"); %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<dspace:layout titlekey="jsp.dspace-admin.supervise-no-workspaceitem.title" + style="submission" + navbar="admin" + locbar="link" + parentlink="/dspace-admin" + parenttitlekey="jsp.administer"> + +<h1><fmt:message key="jsp.dspace-admin.supervise-no-workspaceitem.heading"/></h1> + +<p class="alert alert-danger"><fmt:message key="${errorKey}"/></p> + +<div class="text-center"> +<a href="<%= request.getContextPath() %>/dspace-admin/supervise"><fmt:message key="jsp.dspace-admin.supervise-no-workspaceitem.return"/></a> +</div> + +</dspace:layout> 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/modules/xmlui/src/main/webapp/themes/Participatorio/images/dspace-logo-only.png b/dspace-jspui/src/main/webapp/image/dspace-logo-only.png similarity index 100% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/dspace-logo-only.png rename to dspace-jspui/src/main/webapp/image/dspace-logo-only.png diff --git a/dspace-jspui/src/main/webapp/image/logo-cineca-small.png b/dspace-jspui/src/main/webapp/image/logo-cineca-small.png new file mode 100644 index 0000000000000000000000000000000000000000..a972cc1930c4699a334967d0085665287f7a27b2 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/logo-cineca-small.png differ diff --git a/dspace-jspui/src/main/webapp/image/logo.gif b/dspace-jspui/src/main/webapp/image/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..160f2178bdb5646b93a0c0b24a2c1315829e0f3b Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/logo.gif differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv-error.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv-error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..48b2e4085dc1bc8155b7bb0121b52b136b42f025 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv-error.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv.jpg new file mode 100644 index 0000000000000000000000000000000000000000..995a276d3e1229565fe7a3eafa47f716f663e233 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-arxiv.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-bibtex.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-bibtex.jpg new file mode 100644 index 0000000000000000000000000000000000000000..098ca543be12370c5c58c03233de954d942cd61c Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-bibtex.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii-error.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii-error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a38d8c7e9b522ea8ff321c05c22bad57fa214dca Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii-error.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii.jpg new file mode 100644 index 0000000000000000000000000000000000000000..149a92de2999fffbf2fb5acf4c5eb43edecb7634 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-cinii.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref-error.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref-error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ed10776635358ae11e1908e4bcadc638eb458fe Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref-error.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9025c4c65e04bde06c5a2e50cd049a6ef31ff4ef Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-crossref.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-csv.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-csv.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6e156671bad9e5637599e2988a6ceb7a66adbd7b Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-csv.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-endnote.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-endnote.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d11fa1fd45373a93d0f676d47d220d1c025ce3d6 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-endnote.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed-error.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed-error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c7c92179a7ceb9eb04c0f2deaa4cc87a607aca95 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed-error.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed.jpg new file mode 100644 index 0000000000000000000000000000000000000000..27ceb98a4a23d6bfe817ca829b1f6b422d776c5e Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-pubmed.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-ris.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-ris.jpg new file mode 100644 index 0000000000000000000000000000000000000000..24b49bdbe11416c269a3f41f6093244ae3066bc1 Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-ris.jpg differ diff --git a/dspace-jspui/src/main/webapp/image/submission-lookup-small-tsv.jpg b/dspace-jspui/src/main/webapp/image/submission-lookup-small-tsv.jpg new file mode 100644 index 0000000000000000000000000000000000000000..05de25f60a8885e1711bb410255697012b736b7d Binary files /dev/null and b/dspace-jspui/src/main/webapp/image/submission-lookup-small-tsv.jpg differ 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/footer-submission.jsp b/dspace-jspui/src/main/webapp/layout/footer-submission.jsp new file mode 100644 index 0000000000000000000000000000000000000000..b894d16ccac872c22ab66d7dd3ef2b9a629be136 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/footer-submission.jsp @@ -0,0 +1,14 @@ +<%-- + + 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/ + +--%> +<%-- + - Footer for submission + --%> + +<%@ include file="footer-default.jsp" %> \ 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/header-submission.jsp b/dspace-jspui/src/main/webapp/layout/header-submission.jsp new file mode 100644 index 0000000000000000000000000000000000000000..3bee332a9426153e9477db4f5d144ed7308089ad --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/header-submission.jsp @@ -0,0 +1,166 @@ +<%-- + + 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/ + +--%> +<%-- + - HTML header for main home page + --%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.util.List"%> +<%@ page import="java.util.Enumeration"%> +<%@ page import="org.dspace.app.webui.util.JSPManager" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.app.util.Util" %> +<%@ page import="javax.servlet.jsp.jstl.core.*" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.*" %> + +<% + String title = (String) request.getAttribute("dspace.layout.title"); + String navbar = (String) request.getAttribute("dspace.layout.navbar"); + boolean locbar = ((Boolean) request.getAttribute("dspace.layout.locbar")).booleanValue(); + + String siteName = ConfigurationManager.getProperty("dspace.name"); + String feedRef = (String)request.getAttribute("dspace.layout.feedref"); + boolean osLink = ConfigurationManager.getBooleanProperty("websvc.opensearch.autolink"); + String osCtx = ConfigurationManager.getProperty("websvc.opensearch.svccontext"); + String osName = ConfigurationManager.getProperty("websvc.opensearch.shortname"); + List parts = (List)request.getAttribute("dspace.layout.linkparts"); + String extraHeadData = (String)request.getAttribute("dspace.layout.head"); + String extraHeadDataLast = (String)request.getAttribute("dspace.layout.head.last"); + String dsVersion = Util.getSourceVersion(); + String generator = dsVersion == null ? "DSpace" : "DSpace "+dsVersion; + String analyticsKey = ConfigurationManager.getProperty("jspui.google.analytics.key"); +%> + +<!DOCTYPE html> +<html> + <head> + <title><%= title %> | <%= siteName %></title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta name="Generator" content="<%= generator %>" /> + <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() %>/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)) + { + for (int i = 0; i < parts.size(); i+= 3) + { +%> + <link rel="alternate" type="application/<%= (String)parts.get(i) %>" title="<%= (String)parts.get(i+1) %>" href="<%= request.getContextPath() %>/feed/<%= (String)parts.get(i+2) %>/<%= feedRef %>"/> +<% + } + } + + if (osLink) + { +%> + <link rel="search" type="application/opensearchdescription+xml" href="<%= request.getContextPath() %>/<%= osCtx %>description.xml" title="<%= osName %>"/> +<% + } + + if (extraHeadData != null) + { %> +<%= extraHeadData %> +<% + } +%> + + <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/choice-support.js"> </script> + + <%--Gooogle Analytics recording.--%> + <% + if (analyticsKey != null && analyticsKey.length() > 0) + { + %> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', '<%= analyticsKey %>']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + <% + } + if (extraHeadDataLast != null) + { %> + <%= extraHeadDataLast %> + <% + } + %> + + +<!-- 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 class="undernavigation"> +<a class="sr-only" href="#content">Skip navigation</a> +<header class="navbar navbar-inverse navbar-fixed-top"> + <% + if (!navbar.equals("off")) + { +%> + <div class="container"> + <dspace:include page="<%= navbar %>" /> + </div> +<% + } + else + { + %> + <div class="container"> + <dspace:include page="/layout/navbar-minimal.jsp" /> + </div> +<% + } +%> +</header> + +<main id="content" role="main"> + <%-- 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/legacy/footer-default.jsp b/dspace-jspui/src/main/webapp/layout/legacy/footer-default.jsp new file mode 100644 index 0000000000000000000000000000000000000000..309660dbd7a1cf47b03d92e9d32cf0c7cbdbbdb8 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/footer-default.jsp @@ -0,0 +1,69 @@ +<%-- + + 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/ + +--%> +<%-- + - Footer for home page + --%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.net.URLEncoder" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> + +<% + 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"> + <%= sidebar %> + </td> +<% + } +%> + </tr> + + <%-- 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"/> - + <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> + </body> +</html> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/layout/legacy/footer-popup.jsp b/dspace-jspui/src/main/webapp/layout/legacy/footer-popup.jsp new file mode 100644 index 0000000000000000000000000000000000000000..3df963513ea56d68df7486f535cf378f6bef2b49 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/footer-popup.jsp @@ -0,0 +1,20 @@ +<%-- + + 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/ + +--%> +<%-- + - Footer for home page + --%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + + + </body> +</html> diff --git a/dspace-jspui/src/main/webapp/layout/legacy/header-default.jsp b/dspace-jspui/src/main/webapp/layout/legacy/header-default.jsp new file mode 100644 index 0000000000000000000000000000000000000000..73e8c03c20c2550a24eebed4f1a684e9d983c4a8 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/header-default.jsp @@ -0,0 +1,180 @@ +<%-- + + 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/ + +--%> +<%-- + - HTML header for main home page + --%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.util.List"%> +<%@ page import="java.util.Enumeration"%> +<%@ page import="org.dspace.app.webui.util.JSPManager" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.app.util.Util" %> +<%@ page import="javax.servlet.jsp.jstl.core.*" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.*" %> + +<% + String title = (String) request.getAttribute("dspace.layout.title"); + String navbar = (String) request.getAttribute("dspace.layout.navbar"); + boolean locbar = ((Boolean) request.getAttribute("dspace.layout.locbar")).booleanValue(); + + String siteName = ConfigurationManager.getProperty("dspace.name"); + String feedRef = (String)request.getAttribute("dspace.layout.feedref"); + boolean osLink = ConfigurationManager.getBooleanProperty("websvc.opensearch.autolink"); + String osCtx = ConfigurationManager.getProperty("websvc.opensearch.svccontext"); + String osName = ConfigurationManager.getProperty("websvc.opensearch.shortname"); + List parts = (List)request.getAttribute("dspace.layout.linkparts"); + String extraHeadData = (String)request.getAttribute("dspace.layout.head"); + String extraHeadDataLast = (String)request.getAttribute("dspace.layout.head.last"); + String dsVersion = Util.getSourceVersion(); + String generator = dsVersion == null ? "DSpace" : "DSpace "+dsVersion; + 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"> +<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" /> + <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.10.3.custom/redmond/jquery-ui-1.10.3.custom.min.css" type="text/css" /> +<% + if (!"NONE".equals(feedRef)) + { + for (int i = 0; i < parts.size(); i+= 3) + { +%> + <link rel="alternate" type="application/<%= (String)parts.get(i) %>" title="<%= (String)parts.get(i+1) %>" href="<%= request.getContextPath() %>/feed/<%= (String)parts.get(i+2) %>/<%= feedRef %>"/> +<% + } + } + + if (osLink) + { +%> + <link rel="search" type="application/opensearchdescription+xml" href="<%= request.getContextPath() %>/<%= osCtx %>description.xml" title="<%= osName %>"/> +<% + } + + if (extraHeadData != null) + { %> +<%= extraHeadData %> +<% + } +%> + + <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() %>/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.--%> + <% + if (analyticsKey != null && analyticsKey.length() > 0) + { + %> + <script type="text/javascript"> + var _gaq = _gaq || []; + _gaq.push(['_setAccount', '<%= analyticsKey %>']); + _gaq.push(['_trackPageview']); + + (function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); + })(); + </script> + <% + } + if (extraHeadDataLast != null) + { %> + <%= extraHeadDataLast %> + <% + } + %> + + </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 --%> +<% + if (!navbar.equals("off")) + { +%> + <td class="navigationBar"> + <dspace:include page="<%= navbar %>" /> + </td> +<% + } +%> + <%-- 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%"> + + <%-- Location bar --%> +<% + if (locbar) + { +%> + <dspace:include page="/layout/location-bar.jsp" /> +<% + } +%> diff --git a/dspace-jspui/src/main/webapp/layout/legacy/header-popup.jsp b/dspace-jspui/src/main/webapp/layout/legacy/header-popup.jsp new file mode 100644 index 0000000000000000000000000000000000000000..52e43614868c1e55f835d891d1b33ea9ee780a2a --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/header-popup.jsp @@ -0,0 +1,73 @@ +<%-- + + 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/ + +--%> +<%-- + - HTML header for main home page + --%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.util.List"%> +<%@ page import="java.util.Enumeration"%> +<%@ page import="org.dspace.app.webui.util.JSPManager" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="javax.servlet.jsp.jstl.core.*" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.*" %> + +<% + String title = (String) request.getAttribute("dspace.layout.title"); + + String navbar = (String) request.getAttribute("dspace.layout.navbar"); + boolean locbar = ((Boolean) request.getAttribute("dspace.layout.locbar")).booleanValue(); + + String siteName = ConfigurationManager.getProperty("dspace.name"); + String feedRef = (String)request.getAttribute("dspace.layout.feedref"); + List parts = (List)request.getAttribute("dspace.layout.linkparts"); + String extraHeadData = (String)request.getAttribute("dspace.layout.head"); +%> + +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + <head> + <title><%= siteName %>: <%= title %></title> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta name="Generator" content="DSpace" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/print.css" media="print" type="text/css" /> + <link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/> +<% + if (extraHeadData != null) + { %> +<%= extraHeadData %> +<% + } +%> + + <script type="text/javascript" src="<%= request.getContextPath() %>/utils.js"></script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/prototype.js"> </script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/effects.js"> </script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/builder.js"> </script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"> </script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/choice-support.js"> </script> + </head> + + <%-- HACK: leftmargin, topmargin: for non-CSS compliant Microsoft IE browser --%> + <%-- HACK: marginwidth, marginheight: for non-CSS compliant Netscape browser --%> + <body> + + <%-- Localization --%> +<%-- <c:if test="${param.locale != null}">--%> +<%-- <fmt:setLocale value="${param.locale}" scope="session" /> --%> +<%-- </c:if> --%> +<%-- <fmt:setBundle basename="Messages" scope="session"/> --%> + + <%-- Page contents --%> diff --git a/dspace-jspui/src/main/webapp/layout/legacy/location-bar.jsp b/dspace-jspui/src/main/webapp/layout/legacy/location-bar.jsp new file mode 100644 index 0000000000000000000000000000000000000000..953d39e024e95b853be7921bcf82a790bcae8f00 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/location-bar.jsp @@ -0,0 +1,59 @@ +<%-- + + 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/ + +--%> +<%-- + - Location bar component + - + - This component displays the "breadcrumb" style navigation aid at the top + - of most screens. + - + - Uses request attributes set in org.dspace.app.webui.jsptag.Layout, and + - hence must only be used as part of the execution of that tag. Plus, + - dspace.layout.locbar should be verified to be true before this is included. + - + - dspace.layout.parenttitles - List of titles of parent pages + - dspace.layout.parentlinks - List of URLs of parent pages, empty string + - for non-links + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.util.List" %> + +<p class="locationBar"> +<% + List parentTitles = (List) request.getAttribute("dspace.layout.parenttitles"); + List parentLinks = (List) request.getAttribute("dspace.layout.parentlinks"); + + for (int i = 0; i < parentTitles.size(); i++) + { + 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("")) + { +%> +<%= s %> > +<% + } + else + { +%> +<a href="<%= request.getContextPath() %><%= u %>"><%= s %></a> > +<% + } +} +%> +</p> diff --git a/dspace-jspui/src/main/webapp/layout/legacy/navbar-admin.jsp b/dspace-jspui/src/main/webapp/layout/legacy/navbar-admin.jsp new file mode 100644 index 0000000000000000000000000000000000000000..43ed88f296cfd9bd0b57d4e7727b34198f0e7552 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/navbar-admin.jsp @@ -0,0 +1,209 @@ +<%-- + + 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/ + +--%> +<%-- + - Navigation bar for admin pages + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="java.util.LinkedList" %> +<%@ page import="java.util.List" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<%@ page import="org.dspace.app.webui.util.UIUtil" %> + + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<% + // Get the current page, minus query string + String currentPage = UIUtil.getOriginalURL(request); + int c = currentPage.indexOf( '?' ); + if( c > -1 ) + { + 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 class="navigationBarItem"> + <td> + <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/curate") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> + </td> + <td nowrap="nowrap" class="navigationBarItem"> + <a href="<%= request.getContextPath() %>/dspace-admin/curate"><fmt:message key="jsp.layout.navbar-admin.curate"/></a> + </td> + </tr> + + <tr> + <td colspan="2"> </td> + </tr> + + <tr class="navigationBarItem"> + <td> + <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/withdrawn") ? "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 class="navigationBarItem"> + <td> + <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/privateitems") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> + </td> + <td nowrap="nowrap" class="navigationBarItem"> + <a href="<%= request.getContextPath() %>/dspace-admin/privateitems"><fmt:message key="jsp.layout.navbar-admin.privateitems"/></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> diff --git a/dspace-jspui/src/main/webapp/layout/legacy/navbar-default.jsp b/dspace-jspui/src/main/webapp/layout/legacy/navbar-default.jsp new file mode 100644 index 0000000000000000000000000000000000000000..f78b16a95462d47808e5c54305c8bcd5affa4b17 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/legacy/navbar-default.jsp @@ -0,0 +1,244 @@ +<%-- + + 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/ + +--%> +<%-- + - Default navigation bar +--%> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="/WEB-INF/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.List" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.content.Collection" %> +<%@ page import="org.dspace.content.Community" %> +<%@ page import="org.dspace.eperson.EPerson" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.browse.BrowseIndex" %> +<%@ page import="org.dspace.browse.BrowseInfo" %> +<%@ page import="java.util.Map" %> +<% + // Is anyone logged in? + EPerson user = (EPerson) request.getAttribute("dspace.current.user"); + + // Is the logged in user an admin + Boolean admin = (Boolean)request.getAttribute("is.admin"); + boolean isAdmin = (admin == null ? false : admin.booleanValue()); + + // Get the current page, minus query string + String currentPage = UIUtil.getOriginalURL(request); + int c = currentPage.indexOf( '?' ); + if( c > -1 ) + { + currentPage = currentPage.substring( 0, c ); + } + + // E-mail may have to be truncated + String navbarEmail = null; + + if (user != null) + { + navbarEmail = user.getEmail(); + if (navbarEmail.length() > 18) + { + navbarEmail = navbarEmail.substring(0, 17) + "..."; + } + } + + // get the browse indices + + BrowseIndex[] bis = BrowseIndex.getBrowseIndices(); + BrowseInfo binfo = (BrowseInfo) request.getAttribute("browse.info"); + String browseCurrent = ""; + if (binfo != null) + { + BrowseIndex bix = binfo.getBrowseIndex(); + // Only highlight the current browse, only if it is a metadata index, + // or the selected sort option is the default for the index + if (bix.isMetadataIndex() || bix.getSortOption() == binfo.getSortOption()) + { + if (bix.getName() != null) + browseCurrent = bix.getName(); + } + } +%> + +<%-- Search Box --%> +<form method="get" action="<%= request.getContextPath() %>/simple-search"> + +<% + 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> +<% + if (ConfigurationManager.getBooleanProperty("webui.controlledvocabulary.enable")) + { +%> + <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> 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/layout/navbar-minimal.jsp b/dspace-jspui/src/main/webapp/layout/navbar-minimal.jsp new file mode 100644 index 0000000000000000000000000000000000000000..89566aba8b725382e2f48f7eef8626fd20977269 --- /dev/null +++ b/dspace-jspui/src/main/webapp/layout/navbar-minimal.jsp @@ -0,0 +1,99 @@ +<%-- + + 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/ + +--%> +<%-- + - 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" %> + +<%@ taglib uri="/WEB-INF/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="java.util.ArrayList" %> +<%@ page import="java.util.List" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.content.Collection" %> +<%@ page import="org.dspace.content.Community" %> +<%@ page import="org.dspace.eperson.EPerson" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.browse.BrowseIndex" %> +<%@ page import="org.dspace.browse.BrowseInfo" %> +<%@ page import="java.util.Map" %> +<% + // Is anyone logged in? + EPerson user = (EPerson) request.getAttribute("dspace.current.user"); + + // Is the logged in user an admin + Boolean admin = (Boolean)request.getAttribute("is.admin"); + boolean isAdmin = (admin == null ? false : admin.booleanValue()); + + // Get the current page, minus query string + String currentPage = UIUtil.getOriginalURL(request); + int c = currentPage.indexOf( '?' ); + if( c > -1 ) + { + currentPage = currentPage.substring( 0, c ); + } + + // E-mail may have to be truncated + String navbarEmail = null; + + if (user != null) + { + navbarEmail = user.getEmail(); + } +%> + + + <div class="navbar-header"> + <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"> + <div class="nav navbar-nav navbar-right"> + <ul class="nav navbar-nav navbar-right"> + <li class="dropdown"> + <% + if (user != null) + { + %> + <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> + + </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/requestItem/item-send.jsp b/dspace-jspui/src/main/webapp/requestItem/item-send.jsp new file mode 100644 index 0000000000000000000000000000000000000000..f62d83995728d0dd981c959342d239adecf7e42d --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/item-send.jsp @@ -0,0 +1,33 @@ +<%-- + + 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/ + +--%> +<%-- + - Seggest received OK acknowledgement + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<style type="text/css"> +<!-- +.style1 {color: #0000AE} +--> +</style> + + +<dspace:layout locbar="off" navbar="off" title="O seu registo foi enviado com sucesso"> + + <h1><fmt:message key="jsp.request.item.item-send.info1"/></h1> + + <p><fmt:message key="jsp.request.item.item-send.info2"/> + <a class="style1" href="" onClick="window.close();"><fmt:message key="jsp.request.item.item-send.close"/></a></p> + +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/requestItem/request-form.jsp b/dspace-jspui/src/main/webapp/requestItem/request-form.jsp new file mode 100644 index 0000000000000000000000000000000000000000..c7b81ce96d035776526aca959badcd5f35c19999 --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/request-form.jsp @@ -0,0 +1,113 @@ +<%-- + + 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/ + +--%> +<%-- + - Sugest form JSP + - + - Attributes: + - requestItem.problem - if present, report that all fields weren't filled out + - authenticated.email - email of authenticated user, if any + - handle - URL of handle item + --%> + +<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page import="org.dspace.app.webui.servlet.RequestItemServlet"%> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<% + request.setCharacterEncoding("UTF-8"); + + boolean problem = (request.getAttribute("requestItem.problem") != null); + + String email = (String) request.getAttribute("email"); + if (email == null) + email = ""; + + String userName = (String) request.getAttribute("reqname"); + if (userName == null) + userName = ""; + + String handle = (String) request.getAttribute("handle"); + if (handle == null ) + handle = ""; + + String title = (String) request.getAttribute("title"); + if (title == null) + title = ""; + + String coment = (String) request.getAttribute("coment"); + if (coment == null) + coment = ""; + + String bitstream_id = (String) request.getAttribute("bitstream-id"); + boolean allfiles = (request.getAttribute("allfiles") != null); + +%> + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.request-form.title" > + +<h2><fmt:message key="jsp.request.item.request-form.info2"> +<fmt:param><a href="<%=request.getContextPath()%>/handle/<%=handle %>"><%=title %></a></fmt:param> +</fmt:message></h2> + +<% + if (problem) + { +%> + <p class="alert alert-warning"><fmt:message key="jsp.request.item.request-form.problem"/></p> +<% + } +%> + <form name="form1" class="form-horizontal" action="<%= request.getContextPath() %>/request-item" method="post"> + <div class="form-group"> + <label for="reqname" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-form.reqname"/></label> + <div class="col-md-10"> + <input class="form-control" type="text" name="reqname" size="50" value="<%= userName %>"> + </div> + </div> + <div class="form-group"> + <label for="email" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-form.email"/></label> + <div class="col-md-10"> + <input type="text" class="form-control" name="email" size="50" value="<%= email %>"> + </div> + </div> + <div class="form-group"> + <label for="allfiles" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-form.allfiles"/></label> + <div class="col-md-10"> + <div class="input-group"> + <span class="input-group-addon"><input type="radio" name="allfiles" value="true" <%=allfiles?"checked":""%> /></span> + <span class="form-control"><fmt:message key="jsp.request.item.request-form.yes"/></span> + </div> + <div class="input-group"> + <span class="input-group-addon"><input type="radio" name="allfiles" value="false" <%=allfiles?"":"checked"%> /></span> + <span class="form-control"><fmt:message key="jsp.request.item.request-form.no"/></span> + </div> + </div> + </div> + <div class="form-group"> + <label for="coment" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-form.coment"/></label> + <div class="col-md-10"> + <textarea class="form-control" name="coment" rows="6" cols="46" wrap=soft><%= coment %></textarea> + </div> + </div> + + <input type="hidden" name="handle" value='<%= handle %>' /> + <input type="hidden" name="bitstream-id" value='<%= bitstream_id %>' /> + <input type="hidden" name="step" value="<%=RequestItemServlet.ENTER_FORM_PAGE %>" /> + <div class="btn btn-group col-md-4 pull-right row"> + <a class="btn btn-default col-md-6" href="<%=request.getContextPath()%>/handle/<%=handle %>"><fmt:message key="jsp.request.item.request-form.cancel" /></a> + <button type="submit" name="submit" class="btn btn-primary col-md-6" value="true"><fmt:message key="jsp.request.item.request-form.go"/></button> + </div> + </form> + +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/requestItem/request-free-access.jsp b/dspace-jspui/src/main/webapp/requestItem/request-free-access.jsp new file mode 100644 index 0000000000000000000000000000000000000000..7d3796b3e833fd31e9ec6f555babed817215f791 --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/request-free-access.jsp @@ -0,0 +1,64 @@ +<%-- + + 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/ + +--%> +<%-- + - request-free-acess JSP + - + - Attributes: + - token - token from the request item + - title - + - handle - URL of handle item + - + --%> + +<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page import="org.dspace.app.webui.servlet.RequestItemServlet"%> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<% + String token = request.getParameter("token"); + + String handle = (String) request.getAttribute("handle"); + if (handle == null) + handle = ""; + + String title = (String) request.getAttribute("title"); + if (title == null) + title = ""; +%> + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.request-free-acess.title" > + +<p class="alert alert-success"><fmt:message key="jsp.request.item.request-free-acess.info1"/></p> + +<p><b><fmt:message key="jsp.request.item.request-free-acess.info2" /></b></p> + + <form name="form1" action="<%= request.getContextPath() %>/request-item" method="post" class="form-horizontal"> + <input type="hidden" name="token" value='<%= token %>'> + <input type="hidden" name="step" value='<%= RequestItemServlet.RESUME_FREEACESS %>'> + <div class="form-group"> + <label for="name" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-free-acess.name"/></label> + <div class="col-md-5"> + <input type="text" class="form-control" name="name" size="50" value="" /> + </div> + </div> + <div class="form-group"> + <label for="email" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-free-acess.email"/></label> + <div class="col-md-5"> + <input type="text" name="email" class="form-control" size="50" value="" /> + </div> + </div> + <input class="btn btn-success col-md-offset-2" type="submit" name="submit_free" value="<fmt:message key="jsp.request.item.request-free-acess.free"/>" /> + </form> + +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/requestItem/request-information.jsp b/dspace-jspui/src/main/webapp/requestItem/request-information.jsp new file mode 100644 index 0000000000000000000000000000000000000000..d9266f487c109021fb8d5c27f551be79bab0d722 --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/request-information.jsp @@ -0,0 +1,62 @@ +<%-- + + 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/ + +--%> +<%-- + - request-information JSP + - + - Attributes: + - token - + - handle - URL of handle item + - title - + - request-name - + --%> + +<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page import="org.dspace.app.webui.servlet.RequestItemServlet"%> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<% + String token = request.getParameter("token"); + + String handle = (String) request.getAttribute("handle"); + if (handle == null) + handle = ""; + + String title = (String) request.getAttribute("title"); + if (title == null) + title = ""; + + String requestName = (String) request.getAttribute("request-name"); + if (requestName == null) + requestName = ""; + +%> + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.request-information.title" > +<h2><fmt:message key="jsp.request.item.request-information.info1" /></h2> +<p><fmt:message key="jsp.request.item.request-information.info2"> +<fmt:param><a href="<%=request.getContextPath()%>/handle/<%=handle %>"><%=title %></a></fmt:param> +<fmt:param><%=requestName %></a></fmt:param> +</fmt:message></p> +<p class="alert alert-info"><fmt:message key="jsp.request.item.request-information.note" /></p> +<form name="form1" action="<%= request.getContextPath() %>/request-item" method="post"> + <input type="hidden" name="token" value='<%= token %>' /> + <input type="hidden" name="step" value='<%=RequestItemServlet.APROVE_TOKEN %>' /> + <div class="text-center"> + <input class="btn btn-danger" type="submit" name="submit_no" value="<fmt:message key="jsp.request.item.request-information.no"/>" /> + <input class="btn btn-success" type="submit" name="submit_yes" value="<fmt:message key="jsp.request.item.request-information.yes"/>" /> + </div> + </div> +</form> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/requestItem/request-letter.jsp b/dspace-jspui/src/main/webapp/requestItem/request-letter.jsp new file mode 100644 index 0000000000000000000000000000000000000000..ed6078843c6b3596a57f3559cb2035859d7d2d2f --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/request-letter.jsp @@ -0,0 +1,72 @@ +<%-- + + 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/ + +--%> +<%-- + - request-information JSP + - + - Attributes: + - requestItem.problem - if present, report that all fields weren't filled out + - authenticated.email - email of authenticated user, if any + - handle - URL of handle item + --%> + +<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<%@ page import="org.dspace.app.webui.servlet.RequestItemServlet"%> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<% + String token = request.getParameter("token"); + + String subject = (String) request.getAttribute("subject"); + if (subject == null) + subject = ""; + + String message = (String) request.getAttribute("message"); + if (message == null) + message = ""; + + boolean resp = (Boolean) request.getAttribute("response"); +%> + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.request-letter.title" > + +<% if(resp) { %> + <h2><fmt:message key="jsp.request.item.request-letter.accept.heading" /></h2> + <p><fmt:message key="jsp.request.item.request-letter.accept.info" /></p> +<% } else { %> + <h2><fmt:message key="jsp.request.item.request-letter.reject.heading" /></h2> + <p><fmt:message key="jsp.request.item.request-letter.reject.info" /></p> +<% } %> + <form name="form1" action="<%= request.getContextPath() %>/request-item" method="post" class="form-horizontal"> + <input type="hidden" name="token" value='<%= token %>' /> + <input type="hidden" name="accept_request" value="<%= resp %>" /> + <input type="hidden" name="step" value="<%=RequestItemServlet.RESUME_REQUEST %>" /> + <div class="form-group"> + <label for="subject" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-letter.subject"/></label> + <div class="col-md-10"> + <input type="text" class="form-control" name="subject" value='<%= subject %>' /> + </div> + </div> + <div class="form-group"> + <label for="message" class="control-label col-md-2"><fmt:message key="jsp.request.item.request-letter.message"/></label> + <div class="col-md-10"> + <textarea class="form-control" name="message" rows="20" cols="100"><%= message %></textarea> + </div> + </div> + <div class="btn btn-group col-md-4 pull-right row"> + <input type="submit" name="submit_back" class="btn btn-default col-md-6" value="<fmt:message key="jsp.request.item.request-letter.back"/>" > + <input type="submit" class="btn btn-<%= resp?"success":"reject" %> col-md-6" name="submit_next" value="<fmt:message key="jsp.request.item.request-letter.next"/>" > + </div> + </form> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/requestItem/request-send.jsp b/dspace-jspui/src/main/webapp/requestItem/request-send.jsp new file mode 100644 index 0000000000000000000000000000000000000000..ebb69b830cc909e01cf54c64631ff72719252b75 --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/request-send.jsp @@ -0,0 +1,26 @@ +<%-- + + 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/ + +--%> +<%-- + - request-item received OK acknowledgement + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.request-send.title"> + + <h2><fmt:message key="jsp.request.item.request-send.info1"/></h2> + + <p><fmt:message key="jsp.request.item.request-send.info2"/> + <a href="<%= request.getContextPath() %>/handle/${handle}"><fmt:message key="jsp.request.item.return-item"/></a></p> + +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/requestItem/response-send.jsp b/dspace-jspui/src/main/webapp/requestItem/response-send.jsp new file mode 100644 index 0000000000000000000000000000000000000000..bc7bcc3d9184e6509282cf4bb36f4d91c557471f --- /dev/null +++ b/dspace-jspui/src/main/webapp/requestItem/response-send.jsp @@ -0,0 +1,33 @@ +<%-- + + 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/ + +--%> +<%-- + - response-send received OK acknowledgement + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<style type="text/css"> +<!-- +.style1 {color: #0000AE} +--> +</style> + + +<dspace:layout locbar="off" navbar="default" titlekey="jsp.request.item.response-send.title"> + + <h1><fmt:message key="jsp.request.item.response-send.info1"/></h1> + + <p><fmt:message key="jsp.request.item.response-send.info2"/> + <a href="<%= request.getContextPath() %>/handle/${handle}"><fmt:message key="jsp.request.item.return-item"/></a></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/sherpa/css/sherpa.css b/dspace-jspui/src/main/webapp/sherpa/css/sherpa.css new file mode 100644 index 0000000000000000000000000000000000000000..fd3d21473e6012b5b208a00a29864f537ff25c7c --- /dev/null +++ b/dspace-jspui/src/main/webapp/sherpa/css/sherpa.css @@ -0,0 +1,40 @@ +/** + * 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/ + */ +.sherpaDisclaimer {font-size: 80%; color: #4770AD; } +p.sherpaDisclaimer img {margin: 15px;} + +.sherpaTools { + display: none; +} +div.policy div p img {margin: 10px;display: inline-block;} +.greenRomeoPublisher {background-color: #D0F9D2; } +.blueRomeoPublisher {background-color: #D3ECFA;} +.yellowRomeoPublisher {background-color: #FFFFDF;} +.whiteRomeoPublisher {background-color: #FFFFFF;} +.grayRomeoPublisher {background-color: #F5F5F5;} + +.RomeoPublisher .header, .RomeoPublisher .header a {color: black; } +.greenRomeoPublisher .header, .greenRomeoPublisher .header a {background-color: green; color: white; } +.blueRomeoPublisher .header, .blueRomeoPublisher .header a {background-color: blue; color: white;} +.yellowRomeoPublisher .header,.yellowRomeoPublisher .header a {background-color: yellow; color: black;} +.whiteRomeoPublisher .header, .whiteRomeoPublisher .header a {background-color: white; color: black;} +.grayRomeoPublisher .header, .grayRomeoPublisher .header a {background-color: grey; color:white;} + +.sherpaBox img { + float: left; + margin: 10px; +} + +.sherpaBox .policy img { + float: none; + margin: 2px; +} + +table.romeoColour { + padding: 5px; +} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/sherpa/image/ajax-loader-big.gif b/dspace-jspui/src/main/webapp/sherpa/image/ajax-loader-big.gif new file mode 100644 index 0000000000000000000000000000000000000000..8f5bd01a73cc310e583a4e8a841d60e33d73419d Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/ajax-loader-big.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/image/can.gif b/dspace-jspui/src/main/webapp/sherpa/image/can.gif new file mode 100644 index 0000000000000000000000000000000000000000..2df36dccb86fe276372f4c291b08c9cd76223296 Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/can.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/image/cannot.gif b/dspace-jspui/src/main/webapp/sherpa/image/cannot.gif new file mode 100644 index 0000000000000000000000000000000000000000..d62ceca087f17c8568b5305fc6a9ccb71b19d3af Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/cannot.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/image/restricted.gif b/dspace-jspui/src/main/webapp/sherpa/image/restricted.gif new file mode 100644 index 0000000000000000000000000000000000000000..07b2ed744a9f5e6dd179d9bcfa37dd56df6a564b Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/restricted.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/image/romeosmall.gif b/dspace-jspui/src/main/webapp/sherpa/image/romeosmall.gif new file mode 100644 index 0000000000000000000000000000000000000000..08d175d804fab134f4923dc557de943614340770 Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/romeosmall.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/image/unclear.gif b/dspace-jspui/src/main/webapp/sherpa/image/unclear.gif new file mode 100644 index 0000000000000000000000000000000000000000..313c1dc4fa7d000a93b5f1dfcadccc5ee11e1623 Binary files /dev/null and b/dspace-jspui/src/main/webapp/sherpa/image/unclear.gif differ diff --git a/dspace-jspui/src/main/webapp/sherpa/sherpa-policy.jsp b/dspace-jspui/src/main/webapp/sherpa/sherpa-policy.jsp new file mode 100644 index 0000000000000000000000000000000000000000..1ce2dea1a01e35c5378c4a33862aff165be1bed2 --- /dev/null +++ b/dspace-jspui/src/main/webapp/sherpa/sherpa-policy.jsp @@ -0,0 +1,136 @@ +<%-- + + 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/ + +--%> +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> +<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%> +<fmt:message key="jsp.sherpa.heading"> + <fmt:param value="<%=request.getContextPath()%>" /> +</fmt:message> +<c:choose> +<c:when test="${error}"> + <fmt:message key="jsp.sherpa.error" /> +</c:when> +<c:otherwise> + <c:choose> + <c:when test="${empty result or fn:length(result) == 0}"> + <fmt:message key="jsp.sherpa.noresult" /> + </c:when> + <c:otherwise> + <c:choose> + <c:when test="${fn:length(result) == 1}"> + <fmt:message key="jsp.sherpa.oneresult" /> + </c:when> + <c:otherwise> + <fmt:message key="jsp.sherpa.moreresults" /> + </c:otherwise> + </c:choose> + + <c:forEach var="r" items="${result}"> + <div class="${r[1].romeocolour}RomeoPublisher row"> + <div class="header container"> + <fmt:message key="jsp.sherpa.jornaltitle"> + <fmt:param value="${r[0].title}" /> + </fmt:message> + <fmt:message key="jsp.sherpa.jornalissn"> + <fmt:param value="${r[0].issn}" /> + </fmt:message> + <c:choose> + <c:when test="${empty r[1]}"> + <fmt:message key="jsp.sherpa.publisher.unknow" /> + </c:when> + <c:when test="${empty r[0].romeopub}"> + <fmt:message key="jsp.sherpa.publisher.onlyname"> + <fmt:param value="${r[0].romeopub}" /> + </fmt:message> + </c:when> + <c:otherwise> + <fmt:message key="jsp.sherpa.publisher"> + <fmt:param value="${r[1].name}" /> + <fmt:param value="${r[1].homeurl}" /> + </fmt:message> + </c:otherwise> + </c:choose> + </div> + <div class="policy container"> + <c:choose> + <c:when test="${empty r[1]}"> + <fmt:message key="jsp.sherpa.publisher.nodata" /> + </c:when> + <c:otherwise> + <div class="sherpaPre"> + <fmt:message key="jsp.sherpa.pre-print.${r[1].prearchiving}"> + <fmt:param value="<%=request.getContextPath()%>" /> + </fmt:message> + <c:if test="${r[1].prearchiving eq 'restricted'}"> + <ul><c:forEach var="cond" items="${r[1].prerestriction}"><li>${cond}</li></c:forEach></ul> + </c:if> + </div> + + <div class="sherpaPost"> + <fmt:message key="jsp.sherpa.post-print.${r[1].postarchiving}"> + <fmt:param value="<%=request.getContextPath()%>" /> + </fmt:message> + <c:if test="${r[1].postarchiving eq 'restricted'}"> + <ul><c:forEach var="cond" items="${r[1].postrestriction}"><li>${cond}</li></c:forEach></ul> + </c:if> + </div> + + <div class="sherpaPub"> + <fmt:message key="jsp.sherpa.publisher-version.${r[1].pubarchiving}"> + <fmt:param value="<%=request.getContextPath()%>" /> + </fmt:message> + <c:if test="${r[1].pubarchiving eq 'restricted'}"> + <ul><c:forEach var="cond" items="${r[1].pubrestriction}"><li>${cond}</li></c:forEach></ul> + </c:if> + </div> + + <div class="sherpaConditions"> + <fmt:message key="jsp.sherpa.generalconditions" /> + <ul><c:forEach var="cond" items="${r[1].condition}"><li>${cond}</li></c:forEach></ul> + </div> + + <div class="sherpaPaid"> + <fmt:message key="jsp.sherpa.paidoption"> + <fmt:param value="${r[1].paidaccessname}" /> + <fmt:param value="${r[1].paidaccessurl}" /> + <c:choose> + <c:when test="${!empty r[1].paidaccessnotes}"> + <fmt:param value="${r[1].paidaccessnotes}" /> + </c:when> + <c:otherwise> + <fmt:param value="" /> + </c:otherwise> + </c:choose> + </fmt:message> + </div> + + <div class="sherpaCopyright"> + <fmt:message key="jsp.sherpa.copyright" /> + <ul><c:forEach var="copyright" items="${r[1].copyright}"><li><a href="${copyright[1]}" target="_blank">${copyright[0]}</a></li></c:forEach></ul> + </div> + + <div class="sherpaColor"> + <fmt:message key="jsp.sherpa.publisher.romeocolour"> + <fmt:param value="${r[1].romeocolour}" /> + </fmt:message> + </div> + </c:otherwise> + </c:choose> + </div> + <fmt:message key="jsp.sherpa.legend" /> + </div> + </c:forEach> + </c:otherwise> + </c:choose> +</c:otherwise> +</c:choose> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.css b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.css new file mode 100644 index 0000000000000000000000000000000000000000..ad1173569371a2d189a3783ceb5177af79812719 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.css @@ -0,0 +1,384 @@ +.btn-default, +.btn-primary, +.btn-success, +.btn-info, +.btn-warning, +.btn-danger { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.btn-default:active, +.btn-primary:active, +.btn-success:active, +.btn-info:active, +.btn-warning:active, +.btn-danger:active, +.btn-default.active, +.btn-primary.active, +.btn-success.active, +.btn-info.active, +.btn-warning.active, +.btn-danger.active { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn:active, +.btn.active { + background-image: none; +} + +.btn-default { + text-shadow: 0 1px 0 #fff; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#e6e6e6)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #e6e6e6, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #e6e6e6 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #e6e6e6 100%); + background-repeat: repeat-x; + border-color: #e0e0e0; + border-color: #ccc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe6e6e6', GradientType=0); +} + +.btn-default:active, +.btn-default.active { + background-color: #e6e6e6; + border-color: #e0e0e0; +} + +.btn-primary { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + border-color: #2d6ca2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.btn-primary:active, +.btn-primary.active { + background-color: #3071a9; + border-color: #2d6ca2; +} + +.btn-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + border-color: #419641; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.btn-success:active, +.btn-success.active { + background-color: #449d44; + border-color: #419641; +} + +.btn-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + border-color: #eb9316; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.btn-warning:active, +.btn-warning.active { + background-color: #ec971f; + border-color: #eb9316; +} + +.btn-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + border-color: #c12e2a; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.btn-danger:active, +.btn-danger.active { + background-color: #c9302c; + border-color: #c12e2a; +} + +.btn-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + border-color: #2aabd2; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.btn-info:active, +.btn-info.active { + background-color: #31b0d5; + border-color: #2aabd2; +} + +.thumbnail, +.img-thumbnail { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus, +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + background-color: #357ebd; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.navbar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ffffff), to(#f8f8f8)); + background-image: -webkit-linear-gradient(top, #ffffff, 0%, #f8f8f8, 100%); + background-image: -moz-linear-gradient(top, #ffffff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%); + background-repeat: repeat-x; + border-radius: 4px; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075); +} + +.navbar .navbar-nav > .active > a { + background-color: #f8f8f8; +} + +.navbar-brand, +.navbar-nav > li > a { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25); +} + +.navbar-inverse { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#3c3c3c), to(#222222)); + background-image: -webkit-linear-gradient(top, #3c3c3c, 0%, #222222, 100%); + background-image: -moz-linear-gradient(top, #3c3c3c 0%, #222222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); +} + +.navbar-inverse .navbar-nav > .active > a { + background-color: #222222; +} + +.navbar-inverse .navbar-brand, +.navbar-inverse .navbar-nav > li > a { + text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); +} + +.navbar-static-top, +.navbar-fixed-top, +.navbar-fixed-bottom { + border-radius: 0; +} + +.alert { + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.alert-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#c8e5bc)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #c8e5bc, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + background-repeat: repeat-x; + border-color: #b2dba1; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); +} + +.alert-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#b9def0)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #b9def0, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + background-repeat: repeat-x; + border-color: #9acfea; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); +} + +.alert-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#f8efc0)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #f8efc0, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + background-repeat: repeat-x; + border-color: #f5e79e; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); +} + +.alert-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#e7c3c3)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #e7c3c3, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + background-repeat: repeat-x; + border-color: #dca7a7; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); +} + +.progress { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#ebebeb), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #ebebeb, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); +} + +.progress-bar { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3071a9)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3071a9, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); +} + +.progress-bar-success { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5cb85c), to(#449d44)); + background-image: -webkit-linear-gradient(top, #5cb85c, 0%, #449d44, 100%); + background-image: -moz-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); +} + +.progress-bar-info { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#5bc0de), to(#31b0d5)); + background-image: -webkit-linear-gradient(top, #5bc0de, 0%, #31b0d5, 100%); + background-image: -moz-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); +} + +.progress-bar-warning { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f0ad4e), to(#ec971f)); + background-image: -webkit-linear-gradient(top, #f0ad4e, 0%, #ec971f, 100%); + background-image: -moz-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); +} + +.progress-bar-danger { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9534f), to(#c9302c)); + background-image: -webkit-linear-gradient(top, #d9534f, 0%, #c9302c, 100%); + background-image: -moz-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); +} + +.list-group { + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075); +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#3278b3)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #3278b3, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + background-repeat: repeat-x; + border-color: #3278b3; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); +} + +.panel { + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.panel-default > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f5f5f5), to(#e8e8e8)); + background-image: -webkit-linear-gradient(top, #f5f5f5, 0%, #e8e8e8, 100%); + background-image: -moz-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); +} + +.panel-primary > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#428bca), to(#357ebd)); + background-image: -webkit-linear-gradient(top, #428bca, 0%, #357ebd, 100%); + background-image: -moz-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); +} + +.panel-success > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#dff0d8), to(#d0e9c6)); + background-image: -webkit-linear-gradient(top, #dff0d8, 0%, #d0e9c6, 100%); + background-image: -moz-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); +} + +.panel-info > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#d9edf7), to(#c4e3f3)); + background-image: -webkit-linear-gradient(top, #d9edf7, 0%, #c4e3f3, 100%); + background-image: -moz-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); +} + +.panel-warning > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#fcf8e3), to(#faf2cc)); + background-image: -webkit-linear-gradient(top, #fcf8e3, 0%, #faf2cc, 100%); + background-image: -moz-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); +} + +.panel-danger > .panel-heading { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#f2dede), to(#ebcccc)); + background-image: -webkit-linear-gradient(top, #f2dede, 0%, #ebcccc, 100%); + background-image: -moz-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); +} + +.well { + background-image: -webkit-gradient(linear, left 0%, left 100%, from(#e8e8e8), to(#f5f5f5)); + background-image: -webkit-linear-gradient(top, #e8e8e8, 0%, #f5f5f5, 100%); + background-image: -moz-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + background-repeat: repeat-x; + border-color: #dcdcdc; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1); +} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.min.css b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.min.css new file mode 100644 index 0000000000000000000000000000000000000000..cad36b4e600dc09f24c69e7723ce661d19c4ffae --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap-theme.min.css @@ -0,0 +1 @@ +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 1px rgba(0,0,0,0.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn:active,.btn.active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,0%,#e6e6e6,100%);background-image:-moz-linear-gradient(top,#fff 0,#e6e6e6 100%);background-image:linear-gradient(to bottom,#fff 0,#e6e6e6 100%);background-repeat:repeat-x;border-color:#e0e0e0;border-color:#ccc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0)}.btn-default:active,.btn-default.active{background-color:#e6e6e6;border-color:#e0e0e0}.btn-primary{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;border-color:#2d6ca2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.btn-primary:active,.btn-primary.active{background-color:#3071a9;border-color:#2d6ca2}.btn-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;border-color:#419641;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.btn-success:active,.btn-success.active{background-color:#449d44;border-color:#419641}.btn-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;border-color:#eb9316;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.btn-warning:active,.btn-warning.active{background-color:#ec971f;border-color:#eb9316}.btn-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;border-color:#c12e2a;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.btn-danger:active,.btn-danger.active{background-color:#c9302c;border-color:#c12e2a}.btn-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;border-color:#2aabd2;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.btn-info:active,.btn-info.active{background-color:#31b0d5;border-color:#2aabd2}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.navbar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fff),to(#f8f8f8));background-image:-webkit-linear-gradient(top,#fff,0%,#f8f8f8,100%);background-image:-moz-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff8f8f8',GradientType=0);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.15),0 1px 5px rgba(0,0,0,0.075)}.navbar .navbar-nav>.active>a{background-color:#f8f8f8}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,0.25)}.navbar-inverse{background-image:-webkit-gradient(linear,left 0,left 100%,from(#3c3c3c),to(#222));background-image:-webkit-linear-gradient(top,#3c3c3c,0%,#222,100%);background-image:-moz-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c',endColorstr='#ff222222',GradientType=0)}.navbar-inverse .navbar-nav>.active>a{background-color:#222}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,0.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.25),0 1px 2px rgba(0,0,0,0.05)}.alert-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#c8e5bc));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#c8e5bc,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;border-color:#b2dba1;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffc8e5bc',GradientType=0)}.alert-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#b9def0));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#b9def0,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;border-color:#9acfea;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffb9def0',GradientType=0)}.alert-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#f8efc0));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#f8efc0,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;border-color:#f5e79e;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fff8efc0',GradientType=0)}.alert-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#e7c3c3));background-image:-webkit-linear-gradient(top,#f2dede,0%,#e7c3c3,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;border-color:#dca7a7;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffe7c3c3',GradientType=0)}.progress{background-image:-webkit-gradient(linear,left 0,left 100%,from(#ebebeb),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#ebebeb,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb',endColorstr='#fff5f5f5',GradientType=0)}.progress-bar{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3071a9));background-image:-webkit-linear-gradient(top,#428bca,0%,#3071a9,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3071a9',GradientType=0)}.progress-bar-success{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5cb85c),to(#449d44));background-image:-webkit-linear-gradient(top,#5cb85c,0%,#449d44,100%);background-image:-moz-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c',endColorstr='#ff449d44',GradientType=0)}.progress-bar-info{background-image:-webkit-gradient(linear,left 0,left 100%,from(#5bc0de),to(#31b0d5));background-image:-webkit-linear-gradient(top,#5bc0de,0%,#31b0d5,100%);background-image:-moz-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff31b0d5',GradientType=0)}.progress-bar-warning{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f0ad4e),to(#ec971f));background-image:-webkit-linear-gradient(top,#f0ad4e,0%,#ec971f,100%);background-image:-moz-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e',endColorstr='#ffec971f',GradientType=0)}.progress-bar-danger{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9534f),to(#c9302c));background-image:-webkit-linear-gradient(top,#d9534f,0%,#c9302c,100%);background-image:-moz-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f',endColorstr='#ffc9302c',GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.075);box-shadow:0 1px 2px rgba(0,0,0,0.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#3278b3));background-image:-webkit-linear-gradient(top,#428bca,0%,#3278b3,100%);background-image:-moz-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;border-color:#3278b3;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff3278b3',GradientType=0)}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.panel-default>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f5f5f5),to(#e8e8e8));background-image:-webkit-linear-gradient(top,#f5f5f5,0%,#e8e8e8,100%);background-image:-moz-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#ffe8e8e8',GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#428bca),to(#357ebd));background-image:-webkit-linear-gradient(top,#428bca,0%,#357ebd,100%);background-image:-moz-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca',endColorstr='#ff357ebd',GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#dff0d8),to(#d0e9c6));background-image:-webkit-linear-gradient(top,#dff0d8,0%,#d0e9c6,100%);background-image:-moz-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8',endColorstr='#ffd0e9c6',GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#d9edf7),to(#c4e3f3));background-image:-webkit-linear-gradient(top,#d9edf7,0%,#c4e3f3,100%);background-image:-moz-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7',endColorstr='#ffc4e3f3',GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#fcf8e3),to(#faf2cc));background-image:-webkit-linear-gradient(top,#fcf8e3,0%,#faf2cc,100%);background-image:-moz-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3',endColorstr='#fffaf2cc',GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-gradient(linear,left 0,left 100%,from(#f2dede),to(#ebcccc));background-image:-webkit-linear-gradient(top,#f2dede,0%,#ebcccc,100%);background-image:-moz-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede',endColorstr='#ffebcccc',GradientType=0)}.well{background-image:-webkit-gradient(linear,left 0,left 100%,from(#e8e8e8),to(#f5f5f5));background-image:-webkit-linear-gradient(top,#e8e8e8,0%,#f5f5f5,100%);background-image:-moz-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;border-color:#dcdcdc;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8',endColorstr='#fff5f5f5',GradientType=0);-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 3px rgba(0,0,0,0.05),0 1px 0 rgba(255,255,255,0.1)} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.css b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.css new file mode 100644 index 0000000000000000000000000000000000000000..bbda4eed4afdc3cb938da2c517365faaf58545b5 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.css @@ -0,0 +1,6805 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */ + +/*! normalize.css v2.1.0 | MIT License | git.io/normalize */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +audio, +canvas, +video { + display: inline-block; +} + +audio:not([controls]) { + display: none; + height: 0; +} + +[hidden] { + display: none; +} + +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} + +body { + margin: 0; +} + +a:focus { + outline: thin dotted; +} + +a:active, +a:hover { + outline: 0; +} + +h1 { + margin: 0.67em 0; + font-size: 2em; +} + +abbr[title] { + border-bottom: 1px dotted; +} + +b, +strong { + font-weight: bold; +} + +dfn { + font-style: italic; +} + +hr { + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; +} + +mark { + color: #000; + background: #ff0; +} + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +pre { + white-space: pre-wrap; +} + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +img { + border: 0; +} + +svg:not(:root) { + overflow: hidden; +} + +figure { + margin: 0; +} + +fieldset { + padding: 0.35em 0.625em 0.75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} + +legend { + padding: 0; + border: 0; +} + +button, +input, +select, +textarea { + margin: 0; + font-family: inherit; + font-size: 100%; +} + +button, +input { + line-height: normal; +} + +button, +select { + text-transform: none; +} + +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + cursor: pointer; + -webkit-appearance: button; +} + +button[disabled], +html input[disabled] { + cursor: default; +} + +input[type="checkbox"], +input[type="radio"] { + padding: 0; + box-sizing: border-box; +} + +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} + +textarea { + overflow: auto; + vertical-align: top; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +@media print { + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + @page { + margin: 2cm .5cm; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #fff !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} + +*, +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html { + font-size: 62.5%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.428571429; + color: #333333; + background-color: #ffffff; +} + +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input, +select[multiple], +textarea { + background-image: none; +} + +a { + color: #428bca; + text-decoration: none; +} + +a:hover, +a:focus { + color: #2a6496; + text-decoration: underline; +} + +a:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +img { + vertical-align: middle; +} + +.img-responsive { + display: block; + height: auto; + max-width: 100%; +} + +.img-rounded { + border-radius: 6px; +} + +.img-thumbnail { + display: inline-block; + height: auto; + max-width: 100%; + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.img-circle { + border-radius: 50%; +} + +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eeeeee; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0 0 0 0); + border: 0; +} + +p { + margin: 0 0 10px; +} + +.lead { + margin-bottom: 20px; + font-size: 16.099999999999998px; + font-weight: 200; + line-height: 1.4; +} + +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} + +small { + font-size: 85%; +} + +cite { + font-style: normal; +} + +.text-muted { + color: #999999; +} + +.text-primary { + color: #428bca; +} + +.text-warning { + color: #c09853; +} + +.text-danger { + color: #b94a48; +} + +.text-success { + color: #468847; +} + +.text-info { + color: #3a87ad; +} + +.text-left { + text-align: left; +} + +.text-right { + text-align: right; +} + +.text-center { + text-align: center; +} + +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-weight: 500; + line-height: 1.1; +} + +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small { + font-weight: normal; + line-height: 1; + color: #999999; +} + +h1, +h2, +h3 { + margin-top: 20px; + margin-bottom: 10px; +} + +h4, +h5, +h6 { + margin-top: 10px; + margin-bottom: 10px; +} + +h1, +.h1 { + font-size: 36px; +} + +h2, +.h2 { + font-size: 30px; +} + +h3, +.h3 { + font-size: 24px; +} + +h4, +.h4 { + font-size: 18px; +} + +h5, +.h5 { + font-size: 14px; +} + +h6, +.h6 { + font-size: 12px; +} + +h1 small, +.h1 small { + font-size: 24px; +} + +h2 small, +.h2 small { + font-size: 18px; +} + +h3 small, +.h3 small, +h4 small, +.h4 small { + font-size: 14px; +} + +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eeeeee; +} + +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} + +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} + +dl { + margin-bottom: 20px; +} + +dt, +dd { + line-height: 1.428571429; +} + +dt { + font-weight: bold; +} + +dd { + margin-left: 0; +} + +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } + .dl-horizontal dd:before, + .dl-horizontal dd:after { + display: table; + content: " "; + } + .dl-horizontal dd:after { + clear: both; + } + .dl-horizontal dd:before, + .dl-horizontal dd:after { + display: table; + content: " "; + } + .dl-horizontal dd:after { + clear: both; + } +} + +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #999999; +} + +abbr.initialism { + font-size: 90%; + text-transform: uppercase; +} + +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid #eeeeee; +} + +blockquote p { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +blockquote p:last-child { + margin-bottom: 0; +} + +blockquote small { + display: block; + line-height: 1.428571429; + color: #999999; +} + +blockquote small:before { + content: '\2014 \00A0'; +} + +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + border-right: 5px solid #eeeeee; + border-left: 0; +} + +blockquote.pull-right p, +blockquote.pull-right small { + text-align: right; +} + +blockquote.pull-right small:before { + content: ''; +} + +blockquote.pull-right small:after { + content: '\00A0 \2014'; +} + +q:before, +q:after, +blockquote:before, +blockquote:after { + content: ""; +} + +address { + display: block; + margin-bottom: 20px; + font-style: normal; + line-height: 1.428571429; +} + +code, +pre { + font-family: Monaco, Menlo, Consolas, "Courier New", monospace; +} + +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + white-space: nowrap; + background-color: #f9f2f4; + border-radius: 4px; +} + +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.428571429; + color: #333333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #cccccc; + border-radius: 4px; +} + +pre.prettyprint { + margin-bottom: 20px; +} + +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border: 0; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.container:before, +.container:after { + display: table; + content: " "; +} + +.container:after { + clear: both; +} + +.container:before, +.container:after { + display: table; + content: " "; +} + +.container:after { + clear: both; +} + +.row { + margin-right: -15px; + margin-left: -15px; +} + +.row:before, +.row:after { + display: table; + content: " "; +} + +.row:after { + clear: both; +} + +.row:before, +.row:after { + display: table; + content: " "; +} + +.row:after { + clear: both; +} + +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11, +.col-xs-12, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12, +.col-lg-1, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-10, +.col-lg-11, +.col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col-xs-1, +.col-xs-2, +.col-xs-3, +.col-xs-4, +.col-xs-5, +.col-xs-6, +.col-xs-7, +.col-xs-8, +.col-xs-9, +.col-xs-10, +.col-xs-11 { + float: left; +} + +.col-xs-1 { + width: 8.333333333333332%; +} + +.col-xs-2 { + width: 16.666666666666664%; +} + +.col-xs-3 { + width: 25%; +} + +.col-xs-4 { + width: 33.33333333333333%; +} + +.col-xs-5 { + width: 41.66666666666667%; +} + +.col-xs-6 { + width: 50%; +} + +.col-xs-7 { + width: 58.333333333333336%; +} + +.col-xs-8 { + width: 66.66666666666666%; +} + +.col-xs-9 { + width: 75%; +} + +.col-xs-10 { + width: 83.33333333333334%; +} + +.col-xs-11 { + width: 91.66666666666666%; +} + +.col-xs-12 { + width: 100%; +} + +@media (min-width: 768px) { + .container { + max-width: 750px; + } + .col-sm-1, + .col-sm-2, + .col-sm-3, + .col-sm-4, + .col-sm-5, + .col-sm-6, + .col-sm-7, + .col-sm-8, + .col-sm-9, + .col-sm-10, + .col-sm-11 { + float: left; + } + .col-sm-1 { + width: 8.333333333333332%; + } + .col-sm-2 { + width: 16.666666666666664%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-4 { + width: 33.33333333333333%; + } + .col-sm-5 { + width: 41.66666666666667%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-7 { + width: 58.333333333333336%; + } + .col-sm-8 { + width: 66.66666666666666%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-10 { + width: 83.33333333333334%; + } + .col-sm-11 { + width: 91.66666666666666%; + } + .col-sm-12 { + width: 100%; + } + .col-sm-push-1 { + left: 8.333333333333332%; + } + .col-sm-push-2 { + left: 16.666666666666664%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-4 { + left: 33.33333333333333%; + } + .col-sm-push-5 { + left: 41.66666666666667%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-7 { + left: 58.333333333333336%; + } + .col-sm-push-8 { + left: 66.66666666666666%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-10 { + left: 83.33333333333334%; + } + .col-sm-push-11 { + left: 91.66666666666666%; + } + .col-sm-pull-1 { + right: 8.333333333333332%; + } + .col-sm-pull-2 { + right: 16.666666666666664%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-4 { + right: 33.33333333333333%; + } + .col-sm-pull-5 { + right: 41.66666666666667%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-7 { + right: 58.333333333333336%; + } + .col-sm-pull-8 { + right: 66.66666666666666%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-10 { + right: 83.33333333333334%; + } + .col-sm-pull-11 { + right: 91.66666666666666%; + } + .col-sm-offset-1 { + margin-left: 8.333333333333332%; + } + .col-sm-offset-2 { + margin-left: 16.666666666666664%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-4 { + margin-left: 33.33333333333333%; + } + .col-sm-offset-5 { + margin-left: 41.66666666666667%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-7 { + margin-left: 58.333333333333336%; + } + .col-sm-offset-8 { + margin-left: 66.66666666666666%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-10 { + margin-left: 83.33333333333334%; + } + .col-sm-offset-11 { + margin-left: 91.66666666666666%; + } +} + +@media (min-width: 992px) { + .container { + max-width: 970px; + } + .col-md-1, + .col-md-2, + .col-md-3, + .col-md-4, + .col-md-5, + .col-md-6, + .col-md-7, + .col-md-8, + .col-md-9, + .col-md-10, + .col-md-11 { + float: left; + } + .col-md-1 { + width: 8.333333333333332%; + } + .col-md-2 { + width: 16.666666666666664%; + } + .col-md-3 { + width: 25%; + } + .col-md-4 { + width: 33.33333333333333%; + } + .col-md-5 { + width: 41.66666666666667%; + } + .col-md-6 { + width: 50%; + } + .col-md-7 { + width: 58.333333333333336%; + } + .col-md-8 { + width: 66.66666666666666%; + } + .col-md-9 { + width: 75%; + } + .col-md-10 { + width: 83.33333333333334%; + } + .col-md-11 { + width: 91.66666666666666%; + } + .col-md-12 { + width: 100%; + } + .col-md-push-0 { + left: auto; + } + .col-md-push-1 { + left: 8.333333333333332%; + } + .col-md-push-2 { + left: 16.666666666666664%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-4 { + left: 33.33333333333333%; + } + .col-md-push-5 { + left: 41.66666666666667%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-7 { + left: 58.333333333333336%; + } + .col-md-push-8 { + left: 66.66666666666666%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-10 { + left: 83.33333333333334%; + } + .col-md-push-11 { + left: 91.66666666666666%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-pull-1 { + right: 8.333333333333332%; + } + .col-md-pull-2 { + right: 16.666666666666664%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-4 { + right: 33.33333333333333%; + } + .col-md-pull-5 { + right: 41.66666666666667%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-7 { + right: 58.333333333333336%; + } + .col-md-pull-8 { + right: 66.66666666666666%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-10 { + right: 83.33333333333334%; + } + .col-md-pull-11 { + right: 91.66666666666666%; + } + .col-md-offset-0 { + margin-left: 0; + } + .col-md-offset-1 { + margin-left: 8.333333333333332%; + } + .col-md-offset-2 { + margin-left: 16.666666666666664%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-4 { + margin-left: 33.33333333333333%; + } + .col-md-offset-5 { + margin-left: 41.66666666666667%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-7 { + margin-left: 58.333333333333336%; + } + .col-md-offset-8 { + margin-left: 66.66666666666666%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-10 { + margin-left: 83.33333333333334%; + } + .col-md-offset-11 { + margin-left: 91.66666666666666%; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1170px; + } + .col-lg-1, + .col-lg-2, + .col-lg-3, + .col-lg-4, + .col-lg-5, + .col-lg-6, + .col-lg-7, + .col-lg-8, + .col-lg-9, + .col-lg-10, + .col-lg-11 { + float: left; + } + .col-lg-1 { + width: 8.333333333333332%; + } + .col-lg-2 { + width: 16.666666666666664%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-4 { + width: 33.33333333333333%; + } + .col-lg-5 { + width: 41.66666666666667%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-7 { + width: 58.333333333333336%; + } + .col-lg-8 { + width: 66.66666666666666%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-10 { + width: 83.33333333333334%; + } + .col-lg-11 { + width: 91.66666666666666%; + } + .col-lg-12 { + width: 100%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-push-1 { + left: 8.333333333333332%; + } + .col-lg-push-2 { + left: 16.666666666666664%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-4 { + left: 33.33333333333333%; + } + .col-lg-push-5 { + left: 41.66666666666667%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-7 { + left: 58.333333333333336%; + } + .col-lg-push-8 { + left: 66.66666666666666%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-10 { + left: 83.33333333333334%; + } + .col-lg-push-11 { + left: 91.66666666666666%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-pull-1 { + right: 8.333333333333332%; + } + .col-lg-pull-2 { + right: 16.666666666666664%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-4 { + right: 33.33333333333333%; + } + .col-lg-pull-5 { + right: 41.66666666666667%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-7 { + right: 58.333333333333336%; + } + .col-lg-pull-8 { + right: 66.66666666666666%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-10 { + right: 83.33333333333334%; + } + .col-lg-pull-11 { + right: 91.66666666666666%; + } + .col-lg-offset-0 { + margin-left: 0; + } + .col-lg-offset-1 { + margin-left: 8.333333333333332%; + } + .col-lg-offset-2 { + margin-left: 16.666666666666664%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-4 { + margin-left: 33.33333333333333%; + } + .col-lg-offset-5 { + margin-left: 41.66666666666667%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-7 { + margin-left: 58.333333333333336%; + } + .col-lg-offset-8 { + margin-left: 66.66666666666666%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-10 { + margin-left: 83.33333333333334%; + } + .col-lg-offset-11 { + margin-left: 91.66666666666666%; + } +} + +table { + max-width: 100%; + background-color: transparent; +} + +th { + text-align: left; +} + +.table { + width: 100%; + margin-bottom: 20px; +} + +.table thead > tr > th, +.table tbody > tr > th, +.table tfoot > tr > th, +.table thead > tr > td, +.table tbody > tr > td, +.table tfoot > tr > td { + padding: 8px; + line-height: 1.428571429; + vertical-align: top; + border-top: 1px solid #dddddd; +} + +.table thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #dddddd; +} + +.table caption + thead tr:first-child th, +.table colgroup + thead tr:first-child th, +.table thead:first-child tr:first-child th, +.table caption + thead tr:first-child td, +.table colgroup + thead tr:first-child td, +.table thead:first-child tr:first-child td { + border-top: 0; +} + +.table tbody + tbody { + border-top: 2px solid #dddddd; +} + +.table .table { + background-color: #ffffff; +} + +.table-condensed thead > tr > th, +.table-condensed tbody > tr > th, +.table-condensed tfoot > tr > th, +.table-condensed thead > tr > td, +.table-condensed tbody > tr > td, +.table-condensed tfoot > tr > td { + padding: 5px; +} + +.table-bordered { + border: 1px solid #dddddd; +} + +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #dddddd; +} + +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} + +.table-striped > tbody > tr:nth-child(odd) > td, +.table-striped > tbody > tr:nth-child(odd) > th { + background-color: #f9f9f9; +} + +.table-hover > tbody > tr:hover > td, +.table-hover > tbody > tr:hover > th { + background-color: #f5f5f5; +} + +table col[class*="col-"] { + display: table-column; + float: none; +} + +table td[class*="col-"], +table th[class*="col-"] { + display: table-cell; + float: none; +} + +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} + +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td { + background-color: #d0e9c6; + border-color: #c9e2b3; +} + +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; + border-color: #eed3d7; +} + +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td { + background-color: #ebcccc; + border-color: #e6c1c7; +} + +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td { + background-color: #faf2cc; + border-color: #f8e5be; +} + +@media (max-width: 768px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: scroll; + overflow-y: hidden; + border: 1px solid #dddddd; + } + .table-responsive > .table { + margin-bottom: 0; + background-color: #fff; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > thead > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > thead > tr:last-child > td, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} + +fieldset { + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} + +label { + display: inline-block; + margin-bottom: 5px; + font-weight: bold; +} + +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + + line-height: normal; +} + +input[type="file"] { + display: block; +} + +select[multiple], +select[size] { + height: auto; +} + +select optgroup { + font-family: inherit; + font-size: inherit; + font-style: inherit; +} + +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +input[type="number"]::-webkit-outer-spin-button, +input[type="number"]::-webkit-inner-spin-button { + height: auto; +} + +.form-control:-moz-placeholder { + color: #999999; +} + +.form-control::-moz-placeholder { + color: #999999; +} + +.form-control:-ms-input-placeholder { + color: #999999; +} + +.form-control::-webkit-input-placeholder { + color: #999999; +} + +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.428571429; + color: #555555; + vertical-align: middle; + background-color: #ffffff; + border: 1px solid #cccccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; + transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s; +} + +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6); +} + +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + cursor: not-allowed; + background-color: #eeeeee; +} + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 15px; +} + +.radio, +.checkbox { + display: block; + min-height: 20px; + padding-left: 20px; + margin-top: 10px; + margin-bottom: 10px; + vertical-align: middle; +} + +.radio label, +.checkbox label { + display: inline; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} + +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + float: left; + margin-left: -20px; +} + +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} + +.radio-inline, +.checkbox-inline { + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} + +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} + +input[type="radio"][disabled], +input[type="checkbox"][disabled], +.radio[disabled], +.radio-inline[disabled], +.checkbox[disabled], +.checkbox-inline[disabled], +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"], +fieldset[disabled] .radio, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} + +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-sm { + height: 30px; + line-height: 30px; +} + +textarea.input-sm { + height: auto; +} + +.input-lg { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-lg { + height: 45px; + line-height: 45px; +} + +textarea.input-lg { + height: auto; +} + +.has-warning .help-block, +.has-warning .control-label { + color: #c09853; +} + +.has-warning .form-control { + border-color: #c09853; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-warning .form-control:focus { + border-color: #a47e3c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e; +} + +.has-warning .input-group-addon { + color: #c09853; + background-color: #fcf8e3; + border-color: #c09853; +} + +.has-error .help-block, +.has-error .control-label { + color: #b94a48; +} + +.has-error .form-control { + border-color: #b94a48; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-error .form-control:focus { + border-color: #953b39; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392; +} + +.has-error .input-group-addon { + color: #b94a48; + background-color: #f2dede; + border-color: #b94a48; +} + +.has-success .help-block, +.has-success .control-label { + color: #468847; +} + +.has-success .form-control { + border-color: #468847; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); +} + +.has-success .form-control:focus { + border-color: #356635; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b; +} + +.has-success .input-group-addon { + color: #468847; + background-color: #dff0d8; + border-color: #468847; +} + +.form-control-static { + padding-top: 7px; + margin-bottom: 0; +} + +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} + +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +.form-horizontal .control-label, +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} + +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} + +.form-horizontal .form-group:before, +.form-horizontal .form-group:after { + display: table; + content: " "; +} + +.form-horizontal .form-group:after { + clear: both; +} + +.form-horizontal .form-group:before, +.form-horizontal .form-group:after { + display: table; + content: " "; +} + +.form-horizontal .form-group:after { + clear: both; +} + +@media (min-width: 768px) { + .form-horizontal .control-label { + text-align: right; + } +} + +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.428571429; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + border: 1px solid transparent; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -o-user-select: none; + user-select: none; +} + +.btn:focus { + outline: thin dotted #333; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} + +.btn:hover, +.btn:focus { + color: #333333; + text-decoration: none; +} + +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + opacity: 0.65; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-default { + color: #333333; + background-color: #ffffff; + border-color: #cccccc; +} + +.btn-default:hover, +.btn-default:focus, +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + color: #333333; + background-color: #ebebeb; + border-color: #adadad; +} + +.btn-default:active, +.btn-default.active, +.open .dropdown-toggle.btn-default { + background-image: none; +} + +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #ffffff; + border-color: #cccccc; +} + +.btn-primary { + color: #ffffff; + background-color: #428bca; + border-color: #357ebd; +} + +.btn-primary:hover, +.btn-primary:focus, +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + color: #ffffff; + background-color: #3276b1; + border-color: #285e8e; +} + +.btn-primary:active, +.btn-primary.active, +.open .dropdown-toggle.btn-primary { + background-image: none; +} + +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #428bca; + border-color: #357ebd; +} + +.btn-warning { + color: #ffffff; + background-color: #f0ad4e; + border-color: #eea236; +} + +.btn-warning:hover, +.btn-warning:focus, +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + color: #ffffff; + background-color: #ed9c28; + border-color: #d58512; +} + +.btn-warning:active, +.btn-warning.active, +.open .dropdown-toggle.btn-warning { + background-image: none; +} + +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} + +.btn-danger { + color: #ffffff; + background-color: #d9534f; + border-color: #d43f3a; +} + +.btn-danger:hover, +.btn-danger:focus, +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + color: #ffffff; + background-color: #d2322d; + border-color: #ac2925; +} + +.btn-danger:active, +.btn-danger.active, +.open .dropdown-toggle.btn-danger { + background-image: none; +} + +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} + +.btn-success { + color: #ffffff; + background-color: #5cb85c; + border-color: #4cae4c; +} + +.btn-success:hover, +.btn-success:focus, +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + color: #ffffff; + background-color: #47a447; + border-color: #398439; +} + +.btn-success:active, +.btn-success.active, +.open .dropdown-toggle.btn-success { + background-image: none; +} + +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} + +.btn-info { + color: #ffffff; + background-color: #5bc0de; + border-color: #46b8da; +} + +.btn-info:hover, +.btn-info:focus, +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + color: #ffffff; + background-color: #39b3d7; + border-color: #269abc; +} + +.btn-info:active, +.btn-info.active, +.open .dropdown-toggle.btn-info { + background-image: none; +} + +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} + +.btn-link { + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; +} + +.btn-link, +.btn-link:active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} + +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} + +.btn-link:hover, +.btn-link:focus { + color: #2a6496; + text-decoration: underline; + background-color: transparent; +} + +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #999999; + text-decoration: none; +} + +.btn-lg { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-sm, +.btn-xs { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-xs { + padding: 1px 5px; +} + +.btn-block { + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; +} + +.btn-block + .btn-block { + margin-top: 5px; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + opacity: 0; + -webkit-transition: opacity 0.15s linear; + transition: opacity 0.15s linear; +} + +.fade.in { + opacity: 1; +} + +.collapse { + display: none; +} + +.collapse.in { + display: block; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height 0.35s ease; + transition: height 0.35s ease; +} + +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg'); +} + +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-weight: normal; + line-height: 1; +} + +.glyphicon-asterisk:before { + content: "\2a"; +} + +.glyphicon-plus:before { + content: "\2b"; +} + +.glyphicon-euro:before { + content: "\20ac"; +} + +.glyphicon-minus:before { + content: "\2212"; +} + +.glyphicon-cloud:before { + content: "\2601"; +} + +.glyphicon-envelope:before { + content: "\2709"; +} + +.glyphicon-pencil:before { + content: "\270f"; +} + +.glyphicon-glass:before { + content: "\e001"; +} + +.glyphicon-music:before { + content: "\e002"; +} + +.glyphicon-search:before { + content: "\e003"; +} + +.glyphicon-heart:before { + content: "\e005"; +} + +.glyphicon-star:before { + content: "\e006"; +} + +.glyphicon-star-empty:before { + content: "\e007"; +} + +.glyphicon-user:before { + content: "\e008"; +} + +.glyphicon-film:before { + content: "\e009"; +} + +.glyphicon-th-large:before { + content: "\e010"; +} + +.glyphicon-th:before { + content: "\e011"; +} + +.glyphicon-th-list:before { + content: "\e012"; +} + +.glyphicon-ok:before { + content: "\e013"; +} + +.glyphicon-remove:before { + content: "\e014"; +} + +.glyphicon-zoom-in:before { + content: "\e015"; +} + +.glyphicon-zoom-out:before { + content: "\e016"; +} + +.glyphicon-off:before { + content: "\e017"; +} + +.glyphicon-signal:before { + content: "\e018"; +} + +.glyphicon-cog:before { + content: "\e019"; +} + +.glyphicon-trash:before { + content: "\e020"; +} + +.glyphicon-home:before { + content: "\e021"; +} + +.glyphicon-file:before { + content: "\e022"; +} + +.glyphicon-time:before { + content: "\e023"; +} + +.glyphicon-road:before { + content: "\e024"; +} + +.glyphicon-download-alt:before { + content: "\e025"; +} + +.glyphicon-download:before { + content: "\e026"; +} + +.glyphicon-upload:before { + content: "\e027"; +} + +.glyphicon-inbox:before { + content: "\e028"; +} + +.glyphicon-play-circle:before { + content: "\e029"; +} + +.glyphicon-repeat:before { + content: "\e030"; +} + +.glyphicon-refresh:before { + content: "\e031"; +} + +.glyphicon-list-alt:before { + content: "\e032"; +} + +.glyphicon-flag:before { + content: "\e034"; +} + +.glyphicon-headphones:before { + content: "\e035"; +} + +.glyphicon-volume-off:before { + content: "\e036"; +} + +.glyphicon-volume-down:before { + content: "\e037"; +} + +.glyphicon-volume-up:before { + content: "\e038"; +} + +.glyphicon-qrcode:before { + content: "\e039"; +} + +.glyphicon-barcode:before { + content: "\e040"; +} + +.glyphicon-tag:before { + content: "\e041"; +} + +.glyphicon-tags:before { + content: "\e042"; +} + +.glyphicon-book:before { + content: "\e043"; +} + +.glyphicon-print:before { + content: "\e045"; +} + +.glyphicon-font:before { + content: "\e047"; +} + +.glyphicon-bold:before { + content: "\e048"; +} + +.glyphicon-italic:before { + content: "\e049"; +} + +.glyphicon-text-height:before { + content: "\e050"; +} + +.glyphicon-text-width:before { + content: "\e051"; +} + +.glyphicon-align-left:before { + content: "\e052"; +} + +.glyphicon-align-center:before { + content: "\e053"; +} + +.glyphicon-align-right:before { + content: "\e054"; +} + +.glyphicon-align-justify:before { + content: "\e055"; +} + +.glyphicon-list:before { + content: "\e056"; +} + +.glyphicon-indent-left:before { + content: "\e057"; +} + +.glyphicon-indent-right:before { + content: "\e058"; +} + +.glyphicon-facetime-video:before { + content: "\e059"; +} + +.glyphicon-picture:before { + content: "\e060"; +} + +.glyphicon-map-marker:before { + content: "\e062"; +} + +.glyphicon-adjust:before { + content: "\e063"; +} + +.glyphicon-tint:before { + content: "\e064"; +} + +.glyphicon-edit:before { + content: "\e065"; +} + +.glyphicon-share:before { + content: "\e066"; +} + +.glyphicon-check:before { + content: "\e067"; +} + +.glyphicon-move:before { + content: "\e068"; +} + +.glyphicon-step-backward:before { + content: "\e069"; +} + +.glyphicon-fast-backward:before { + content: "\e070"; +} + +.glyphicon-backward:before { + content: "\e071"; +} + +.glyphicon-play:before { + content: "\e072"; +} + +.glyphicon-pause:before { + content: "\e073"; +} + +.glyphicon-stop:before { + content: "\e074"; +} + +.glyphicon-forward:before { + content: "\e075"; +} + +.glyphicon-fast-forward:before { + content: "\e076"; +} + +.glyphicon-step-forward:before { + content: "\e077"; +} + +.glyphicon-eject:before { + content: "\e078"; +} + +.glyphicon-chevron-left:before { + content: "\e079"; +} + +.glyphicon-chevron-right:before { + content: "\e080"; +} + +.glyphicon-plus-sign:before { + content: "\e081"; +} + +.glyphicon-minus-sign:before { + content: "\e082"; +} + +.glyphicon-remove-sign:before { + content: "\e083"; +} + +.glyphicon-ok-sign:before { + content: "\e084"; +} + +.glyphicon-question-sign:before { + content: "\e085"; +} + +.glyphicon-info-sign:before { + content: "\e086"; +} + +.glyphicon-screenshot:before { + content: "\e087"; +} + +.glyphicon-remove-circle:before { + content: "\e088"; +} + +.glyphicon-ok-circle:before { + content: "\e089"; +} + +.glyphicon-ban-circle:before { + content: "\e090"; +} + +.glyphicon-arrow-left:before { + content: "\e091"; +} + +.glyphicon-arrow-right:before { + content: "\e092"; +} + +.glyphicon-arrow-up:before { + content: "\e093"; +} + +.glyphicon-arrow-down:before { + content: "\e094"; +} + +.glyphicon-share-alt:before { + content: "\e095"; +} + +.glyphicon-resize-full:before { + content: "\e096"; +} + +.glyphicon-resize-small:before { + content: "\e097"; +} + +.glyphicon-exclamation-sign:before { + content: "\e101"; +} + +.glyphicon-gift:before { + content: "\e102"; +} + +.glyphicon-leaf:before { + content: "\e103"; +} + +.glyphicon-eye-open:before { + content: "\e105"; +} + +.glyphicon-eye-close:before { + content: "\e106"; +} + +.glyphicon-warning-sign:before { + content: "\e107"; +} + +.glyphicon-plane:before { + content: "\e108"; +} + +.glyphicon-random:before { + content: "\e110"; +} + +.glyphicon-comment:before { + content: "\e111"; +} + +.glyphicon-magnet:before { + content: "\e112"; +} + +.glyphicon-chevron-up:before { + content: "\e113"; +} + +.glyphicon-chevron-down:before { + content: "\e114"; +} + +.glyphicon-retweet:before { + content: "\e115"; +} + +.glyphicon-shopping-cart:before { + content: "\e116"; +} + +.glyphicon-folder-close:before { + content: "\e117"; +} + +.glyphicon-folder-open:before { + content: "\e118"; +} + +.glyphicon-resize-vertical:before { + content: "\e119"; +} + +.glyphicon-resize-horizontal:before { + content: "\e120"; +} + +.glyphicon-hdd:before { + content: "\e121"; +} + +.glyphicon-bullhorn:before { + content: "\e122"; +} + +.glyphicon-certificate:before { + content: "\e124"; +} + +.glyphicon-thumbs-up:before { + content: "\e125"; +} + +.glyphicon-thumbs-down:before { + content: "\e126"; +} + +.glyphicon-hand-right:before { + content: "\e127"; +} + +.glyphicon-hand-left:before { + content: "\e128"; +} + +.glyphicon-hand-up:before { + content: "\e129"; +} + +.glyphicon-hand-down:before { + content: "\e130"; +} + +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} + +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} + +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} + +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} + +.glyphicon-globe:before { + content: "\e135"; +} + +.glyphicon-tasks:before { + content: "\e137"; +} + +.glyphicon-filter:before { + content: "\e138"; +} + +.glyphicon-fullscreen:before { + content: "\e140"; +} + +.glyphicon-dashboard:before { + content: "\e141"; +} + +.glyphicon-heart-empty:before { + content: "\e143"; +} + +.glyphicon-link:before { + content: "\e144"; +} + +.glyphicon-phone:before { + content: "\e145"; +} + +.glyphicon-usd:before { + content: "\e148"; +} + +.glyphicon-gbp:before { + content: "\e149"; +} + +.glyphicon-sort:before { + content: "\e150"; +} + +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} + +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} + +.glyphicon-sort-by-order:before { + content: "\e153"; +} + +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} + +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} + +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} + +.glyphicon-unchecked:before { + content: "\e157"; +} + +.glyphicon-expand:before { + content: "\e158"; +} + +.glyphicon-collapse-down:before { + content: "\e159"; +} + +.glyphicon-collapse-up:before { + content: "\e160"; +} + +.glyphicon-log-in:before { + content: "\e161"; +} + +.glyphicon-flash:before { + content: "\e162"; +} + +.glyphicon-log-out:before { + content: "\e163"; +} + +.glyphicon-new-window:before { + content: "\e164"; +} + +.glyphicon-record:before { + content: "\e165"; +} + +.glyphicon-save:before { + content: "\e166"; +} + +.glyphicon-open:before { + content: "\e167"; +} + +.glyphicon-saved:before { + content: "\e168"; +} + +.glyphicon-import:before { + content: "\e169"; +} + +.glyphicon-export:before { + content: "\e170"; +} + +.glyphicon-send:before { + content: "\e171"; +} + +.glyphicon-floppy-disk:before { + content: "\e172"; +} + +.glyphicon-floppy-saved:before { + content: "\e173"; +} + +.glyphicon-floppy-remove:before { + content: "\e174"; +} + +.glyphicon-floppy-save:before { + content: "\e175"; +} + +.glyphicon-floppy-open:before { + content: "\e176"; +} + +.glyphicon-credit-card:before { + content: "\e177"; +} + +.glyphicon-transfer:before { + content: "\e178"; +} + +.glyphicon-cutlery:before { + content: "\e179"; +} + +.glyphicon-header:before { + content: "\e180"; +} + +.glyphicon-compressed:before { + content: "\e181"; +} + +.glyphicon-earphone:before { + content: "\e182"; +} + +.glyphicon-phone-alt:before { + content: "\e183"; +} + +.glyphicon-tower:before { + content: "\e184"; +} + +.glyphicon-stats:before { + content: "\e185"; +} + +.glyphicon-sd-video:before { + content: "\e186"; +} + +.glyphicon-hd-video:before { + content: "\e187"; +} + +.glyphicon-subtitles:before { + content: "\e188"; +} + +.glyphicon-sound-stereo:before { + content: "\e189"; +} + +.glyphicon-sound-dolby:before { + content: "\e190"; +} + +.glyphicon-sound-5-1:before { + content: "\e191"; +} + +.glyphicon-sound-6-1:before { + content: "\e192"; +} + +.glyphicon-sound-7-1:before { + content: "\e193"; +} + +.glyphicon-copyright-mark:before { + content: "\e194"; +} + +.glyphicon-registration-mark:before { + content: "\e195"; +} + +.glyphicon-cloud-download:before { + content: "\e197"; +} + +.glyphicon-cloud-upload:before { + content: "\e198"; +} + +.glyphicon-tree-conifer:before { + content: "\e199"; +} + +.glyphicon-tree-deciduous:before { + content: "\e200"; +} + +.glyphicon-briefcase:before { + content: "\1f4bc"; +} + +.glyphicon-calendar:before { + content: "\1f4c5"; +} + +.glyphicon-pushpin:before { + content: "\1f4cc"; +} + +.glyphicon-paperclip:before { + content: "\1f4ce"; +} + +.glyphicon-camera:before { + content: "\1f4f7"; +} + +.glyphicon-lock:before { + content: "\1f512"; +} + +.glyphicon-bell:before { + content: "\1f514"; +} + +.glyphicon-bookmark:before { + content: "\1f516"; +} + +.glyphicon-fire:before { + content: "\1f525"; +} + +.glyphicon-wrench:before { + content: "\1f527"; +} + +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid #000000; + border-right: 4px solid transparent; + border-bottom: 0 dotted; + border-left: 4px solid transparent; + content: ""; +} + +.dropdown { + position: relative; +} + +.dropdown-toggle:focus { + outline: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); + background-clip: padding-box; +} + +.dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} + +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.428571429; + color: #333333; + white-space: nowrap; +} + +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #428bca; +} + +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #ffffff; + text-decoration: none; + background-color: #428bca; + outline: 0; +} + +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #999999; +} + +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); +} + +.open > .dropdown-menu { + display: block; +} + +.open > a { + outline: 0; +} + +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.428571429; + color: #999999; +} + +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} + +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} + +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-top: 0 dotted; + border-bottom: 4px solid #000000; + content: ""; +} + +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 1px; +} + +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } +} + +.btn-default .caret { + border-top-color: #333333; +} + +.btn-primary .caret, +.btn-success .caret, +.btn-warning .caret, +.btn-danger .caret, +.btn-info .caret { + border-top-color: #fff; +} + +.dropup .btn-default .caret { + border-bottom-color: #333333; +} + +.dropup .btn-primary .caret, +.dropup .btn-success .caret, +.dropup .btn-warning .caret, +.dropup .btn-danger .caret, +.dropup .btn-info .caret { + border-bottom-color: #fff; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} + +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus { + outline: none; +} + +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} + +.btn-toolbar:before, +.btn-toolbar:after { + display: table; + content: " "; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar:before, +.btn-toolbar:after { + display: table; + content: " "; +} + +.btn-toolbar:after { + clear: both; +} + +.btn-toolbar .btn-group { + float: left; +} + +.btn-toolbar > .btn + .btn, +.btn-toolbar > .btn-group + .btn, +.btn-toolbar > .btn + .btn-group, +.btn-toolbar > .btn-group + .btn-group { + margin-left: 5px; +} + +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group > .btn-group { + float: left; +} + +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +.btn-group > .btn-group:first-child > .btn:last-child, +.btn-group > .btn-group:first-child > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn-group:last-child > .btn:first-child { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} + +.btn-group-xs > .btn { + padding: 5px 10px; + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} + +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} + +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); +} + +.btn .caret { + margin-left: 0; +} + +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} + +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} + +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group { + display: block; + float: none; + width: 100%; + max-width: 100%; +} + +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after { + display: table; + content: " "; +} + +.btn-group-vertical > .btn-group:after { + clear: both; +} + +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after { + display: table; + content: " "; +} + +.btn-group-vertical > .btn-group:after { + clear: both; +} + +.btn-group-vertical > .btn-group > .btn { + float: none; +} + +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} + +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-right-radius: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 0; +} + +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} + +.btn-group-vertical > .btn-group:first-child > .btn:last-child, +.btn-group-vertical > .btn-group:first-child > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn-group:last-child > .btn:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.btn-group-justified { + display: table; + width: 100%; + border-collapse: separate; + table-layout: fixed; +} + +.btn-group-justified .btn { + display: table-cell; + float: none; + width: 1%; +} + +[data-toggle="buttons"] > .btn > input[type="radio"], +[data-toggle="buttons"] > .btn > input[type="checkbox"] { + display: none; +} + +.input-group { + position: relative; + display: table; + border-collapse: separate; +} + +.input-group.col { + float: none; + padding-right: 0; + padding-left: 0; +} + +.input-group .form-control { + width: 100%; + margin-bottom: 0; +} + +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 45px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; +} + +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 45px; + line-height: 45px; +} + +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn { + height: auto; +} + +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} + +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} + +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn { + height: auto; +} + +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} + +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} + +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} + +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + text-align: center; + background-color: #eeeeee; + border: 1px solid #cccccc; + border-radius: 4px; +} + +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} + +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} + +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} + +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group-addon:first-child { + border-right: 0; +} + +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child) { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} + +.input-group-addon:last-child { + border-left: 0; +} + +.input-group-btn { + position: relative; + white-space: nowrap; +} + +.input-group-btn > .btn { + position: relative; +} + +.input-group-btn > .btn + .btn { + margin-left: -4px; +} + +.input-group-btn > .btn:hover, +.input-group-btn > .btn:active { + z-index: 2; +} + +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav:before, +.nav:after { + display: table; + content: " "; +} + +.nav:after { + clear: both; +} + +.nav:before, +.nav:after { + display: table; + content: " "; +} + +.nav:after { + clear: both; +} + +.nav > li { + position: relative; + display: block; +} + +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} + +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.nav > li.disabled > a { + color: #999999; +} + +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #999999; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} + +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eeeeee; + border-color: #428bca; +} + +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} + +.nav > li > a > img { + max-width: none; +} + +.nav-tabs { + border-bottom: 1px solid #dddddd; +} + +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} + +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.428571429; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} + +.nav-tabs > li > a:hover { + border-color: #eeeeee #eeeeee #dddddd; +} + +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555555; + cursor: default; + background-color: #ffffff; + border: 1px solid #dddddd; + border-bottom-color: transparent; +} + +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} + +.nav-tabs.nav-justified > li { + float: none; +} + +.nav-tabs.nav-justified > li > a { + text-align: center; +} + +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } +} + +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-bottom: 1px solid #dddddd; +} + +.nav-tabs.nav-justified > .active > a { + border-bottom-color: #ffffff; +} + +.nav-pills > li { + float: left; +} + +.nav-pills > li > a { + border-radius: 5px; +} + +.nav-pills > li + li { + margin-left: 2px; +} + +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #ffffff; + background-color: #428bca; +} + +.nav-stacked > li { + float: none; +} + +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} + +.nav-justified { + width: 100%; +} + +.nav-justified > li { + float: none; +} + +.nav-justified > li > a { + text-align: center; +} + +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } +} + +.nav-tabs-justified { + border-bottom: 0; +} + +.nav-tabs-justified > li > a { + margin-right: 0; + border-bottom: 1px solid #dddddd; +} + +.nav-tabs-justified > .active > a { + border-bottom-color: #ffffff; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: " "; +} + +.tabbable:after { + clear: both; +} + +.tabbable:before, +.tabbable:after { + display: table; + content: " "; +} + +.tabbable:after { + clear: both; +} + +.tab-content > .tab-pane, +.pill-content > .pill-pane { + display: none; +} + +.tab-content > .active, +.pill-content > .active { + display: block; +} + +.nav .caret { + border-top-color: #428bca; + border-bottom-color: #428bca; +} + +.nav a:hover .caret { + border-top-color: #2a6496; + border-bottom-color: #2a6496; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar { + position: relative; + z-index: 1000; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} + +.navbar:before, +.navbar:after { + display: table; + content: " "; +} + +.navbar:after { + clear: both; +} + +.navbar:before, +.navbar:after { + display: table; + content: " "; +} + +.navbar:after { + clear: both; +} + +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} + +.navbar-header:before, +.navbar-header:after { + display: table; + content: " "; +} + +.navbar-header:after { + clear: both; +} + +.navbar-header:before, +.navbar-header:after { + display: table; + content: " "; +} + +.navbar-header:after { + clear: both; +} + +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} + +.navbar-collapse { + max-height: 340px; + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); + -webkit-overflow-scrolling: touch; +} + +.navbar-collapse:before, +.navbar-collapse:after { + display: table; + content: " "; +} + +.navbar-collapse:after { + clear: both; +} + +.navbar-collapse:before, +.navbar-collapse:after { + display: table; + content: " "; +} + +.navbar-collapse:after { + clear: both; +} + +.navbar-collapse.in { + overflow-y: auto; +} + +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-collapse .navbar-nav.navbar-left:first-child { + margin-left: -15px; + } + .navbar-collapse .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } + .navbar-collapse .navbar-text:last-child { + margin-right: 0; + } +} + +.container > .navbar-header, +.container > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} + +@media (min-width: 768px) { + .container > .navbar-header, + .container > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} + +.navbar-static-top { + border-width: 0 0 1px; +} + +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} + +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + border-width: 0 0 1px; +} + +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} + +.navbar-fixed-top { + top: 0; + z-index: 1030; +} + +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; +} + +.navbar-brand { + float: left; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} + +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} + +@media (min-width: 768px) { + .navbar > .container .navbar-brand { + margin-left: -15px; + } +} + +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + border: 1px solid transparent; + border-radius: 4px; +} + +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} + +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} + +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} + +.navbar-nav { + margin: 7.5px -15px; +} + +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} + +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} + +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} + +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + } +} + +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); +} + +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } +} + +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } +} + +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} + +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.navbar-nav.pull-right > li > .dropdown-menu, +.navbar-nav > li > .dropdown-menu.pull-right { + right: 0; + left: auto; +} + +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} + +.navbar-text { + float: left; + margin-top: 15px; + margin-bottom: 15px; +} + +@media (min-width: 768px) { + .navbar-text { + margin-right: 15px; + margin-left: 15px; + } +} + +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} + +.navbar-default .navbar-brand { + color: #777777; +} + +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} + +.navbar-default .navbar-text { + color: #777777; +} + +.navbar-default .navbar-nav > li > a { + color: #777777; +} + +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333333; + background-color: transparent; +} + +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555555; + background-color: #e7e7e7; +} + +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #cccccc; + background-color: transparent; +} + +.navbar-default .navbar-toggle { + border-color: #dddddd; +} + +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #dddddd; +} + +.navbar-default .navbar-toggle .icon-bar { + background-color: #cccccc; +} + +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e6e6e6; +} + +.navbar-default .navbar-nav > .dropdown > a:hover .caret, +.navbar-default .navbar-nav > .dropdown > a:focus .caret { + border-top-color: #333333; + border-bottom-color: #333333; +} + +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555555; + background-color: #e7e7e7; +} + +.navbar-default .navbar-nav > .open > a .caret, +.navbar-default .navbar-nav > .open > a:hover .caret, +.navbar-default .navbar-nav > .open > a:focus .caret { + border-top-color: #555555; + border-bottom-color: #555555; +} + +.navbar-default .navbar-nav > .dropdown > a .caret { + border-top-color: #777777; + border-bottom-color: #777777; +} + +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #cccccc; + background-color: transparent; + } +} + +.navbar-default .navbar-link { + color: #777777; +} + +.navbar-default .navbar-link:hover { + color: #333333; +} + +.navbar-inverse { + background-color: #222222; + border-color: #080808; +} + +.navbar-inverse .navbar-brand { + color: #999999; +} + +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .navbar-text { + color: #999999; +} + +.navbar-inverse .navbar-nav > li > a { + color: #999999; +} + +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #ffffff; + background-color: transparent; +} + +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #ffffff; + background-color: #080808; +} + +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444444; + background-color: transparent; +} + +.navbar-inverse .navbar-toggle { + border-color: #333333; +} + +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333333; +} + +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #ffffff; +} + +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} + +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #ffffff; + background-color: #080808; +} + +.navbar-inverse .navbar-nav > .dropdown > a:hover .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +.navbar-inverse .navbar-nav > .dropdown > a .caret { + border-top-color: #999999; + border-bottom-color: #999999; +} + +.navbar-inverse .navbar-nav > .open > a .caret, +.navbar-inverse .navbar-nav > .open > a:hover .caret, +.navbar-inverse .navbar-nav > .open > a:focus .caret { + border-top-color: #ffffff; + border-bottom-color: #ffffff; +} + +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999999; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #ffffff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #ffffff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444444; + background-color: transparent; + } +} + +.navbar-inverse .navbar-link { + color: #999999; +} + +.navbar-inverse .navbar-link:hover { + color: #ffffff; +} + +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} + +.breadcrumb > li { + display: inline-block; +} + +.breadcrumb > li + li:before { + padding: 0 5px; + color: #cccccc; + content: "/\00a0"; +} + +.breadcrumb > .active { + color: #999999; +} + +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} + +.pagination > li { + display: inline; +} + +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.428571429; + text-decoration: none; + background-color: #ffffff; + border: 1px solid #dddddd; +} + +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-bottom-left-radius: 4px; + border-top-left-radius: 4px; +} + +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} + +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + background-color: #eeeeee; +} + +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #ffffff; + cursor: default; + background-color: #428bca; + border-color: #428bca; +} + +.pagination > .disabled > span, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #999999; + cursor: not-allowed; + background-color: #ffffff; + border-color: #dddddd; +} + +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} + +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-bottom-left-radius: 6px; + border-top-left-radius: 6px; +} + +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} + +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} + +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-bottom-left-radius: 3px; + border-top-left-radius: 3px; +} + +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} + +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} + +.pager:before, +.pager:after { + display: table; + content: " "; +} + +.pager:after { + clear: both; +} + +.pager:before, +.pager:after { + display: table; + content: " "; +} + +.pager:after { + clear: both; +} + +.pager li { + display: inline; +} + +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 15px; +} + +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eeeeee; +} + +.pager .next > a, +.pager .next > span { + float: right; +} + +.pager .previous > a, +.pager .previous > span { + float: left; +} + +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #999999; + cursor: not-allowed; + background-color: #ffffff; +} + +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} + +.label[href]:hover, +.label[href]:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.label:empty { + display: none; +} + +.label-default { + background-color: #999999; +} + +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #808080; +} + +.label-primary { + background-color: #428bca; +} + +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #3071a9; +} + +.label-success { + background-color: #5cb85c; +} + +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} + +.label-info { + background-color: #5bc0de; +} + +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} + +.label-warning { + background-color: #f0ad4e; +} + +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} + +.label-danger { + background-color: #d9534f; +} + +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} + +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #ffffff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999999; + border-radius: 10px; +} + +.badge:empty { + display: none; +} + +a.badge:hover, +a.badge:focus { + color: #ffffff; + text-decoration: none; + cursor: pointer; +} + +.btn .badge { + position: relative; + top: -1px; +} + +a.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #428bca; + background-color: #ffffff; +} + +.nav-pills > li > a > .badge { + margin-left: 3px; +} + +.jumbotron { + padding: 30px; + margin-bottom: 30px; + font-size: 21px; + font-weight: 200; + line-height: 2.1428571435; + color: inherit; + background-color: #eeeeee; +} + +.jumbotron h1 { + line-height: 1; + color: inherit; +} + +.jumbotron p { + line-height: 1.4; +} + +.container .jumbotron { + border-radius: 6px; +} + +@media screen and (min-width: 768px) { + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1 { + font-size: 63px; + } +} + +.thumbnail { + display: inline-block; + display: block; + height: auto; + max-width: 100%; + padding: 4px; + line-height: 1.428571429; + background-color: #ffffff; + border: 1px solid #dddddd; + border-radius: 4px; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; +} + +.thumbnail > img { + display: block; + height: auto; + max-width: 100%; +} + +a.thumbnail:hover, +a.thumbnail:focus { + border-color: #428bca; +} + +.thumbnail > img { + margin-right: auto; + margin-left: auto; +} + +.thumbnail .caption { + padding: 9px; + color: #333333; +} + +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} + +.alert h4 { + margin-top: 0; + color: inherit; +} + +.alert .alert-link { + font-weight: bold; +} + +.alert > p, +.alert > ul { + margin-bottom: 0; +} + +.alert > p + p { + margin-top: 5px; +} + +.alert-dismissable { + padding-right: 35px; +} + +.alert-dismissable .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} + +.alert-success { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.alert-success hr { + border-top-color: #c9e2b3; +} + +.alert-success .alert-link { + color: #356635; +} + +.alert-info { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.alert-info hr { + border-top-color: #a6e1ec; +} + +.alert-info .alert-link { + color: #2d6987; +} + +.alert-warning { + color: #c09853; + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.alert-warning hr { + border-top-color: #f8e5be; +} + +.alert-warning .alert-link { + color: #a47e3c; +} + +.alert-danger { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.alert-danger hr { + border-top-color: #e6c1c7; +} + +.alert-danger .alert-link { + color: #953b39; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-moz-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +@-o-keyframes progress-bar-stripes { + from { + background-position: 0 0; + } + to { + background-position: 40px 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} + +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + color: #ffffff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + -webkit-transition: width 0.6s ease; + transition: width 0.6s ease; +} + +.progress-striped .progress-bar { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 40px 40px; +} + +.progress.active .progress-bar { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -moz-animation: progress-bar-stripes 2s linear infinite; + -ms-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} + +.progress-bar-success { + background-color: #5cb85c; +} + +.progress-striped .progress-bar-success { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-info { + background-color: #5bc0de; +} + +.progress-striped .progress-bar-info { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-warning { + background-color: #f0ad4e; +} + +.progress-striped .progress-bar-warning { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.progress-bar-danger { + background-color: #d9534f; +} + +.progress-striped .progress-bar-danger { + background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent)); + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); +} + +.media, +.media-body { + overflow: hidden; + zoom: 1; +} + +.media, +.media .media { + margin-top: 15px; +} + +.media:first-child { + margin-top: 0; +} + +.media-object { + display: block; +} + +.media-heading { + margin: 0 0 5px; +} + +.media > .pull-left { + margin-right: 10px; +} + +.media > .pull-right { + margin-left: 10px; +} + +.media-list { + padding-left: 0; + list-style: none; +} + +.list-group { + padding-left: 0; + margin-bottom: 20px; +} + +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #ffffff; + border: 1px solid #dddddd; +} + +.list-group-item:first-child { + border-top-right-radius: 4px; + border-top-left-radius: 4px; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} + +.list-group-item > .badge { + float: right; +} + +.list-group-item > .badge + .badge { + margin-right: 5px; +} + +a.list-group-item { + color: #555555; +} + +a.list-group-item .list-group-item-heading { + color: #333333; +} + +a.list-group-item:hover, +a.list-group-item:focus { + text-decoration: none; + background-color: #f5f5f5; +} + +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} + +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading { + color: inherit; +} + +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #e1edf7; +} + +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} + +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} + +.panel { + margin-bottom: 20px; + background-color: #ffffff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.panel-body { + padding: 15px; +} + +.panel-body:before, +.panel-body:after { + display: table; + content: " "; +} + +.panel-body:after { + clear: both; +} + +.panel-body:before, +.panel-body:after { + display: table; + content: " "; +} + +.panel-body:after { + clear: both; +} + +.panel > .list-group { + margin-bottom: 0; +} + +.panel > .list-group .list-group-item { + border-width: 1px 0; +} + +.panel > .list-group .list-group-item:first-child { + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.panel > .list-group .list-group-item:last-child { + border-bottom: 0; +} + +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} + +.panel > .table { + margin-bottom: 0; +} + +.panel > .panel-body + .table { + border-top: 1px solid #dddddd; +} + +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-right-radius: 3px; + border-top-left-radius: 3px; +} + +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; +} + +.panel-title > a { + color: inherit; +} + +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #dddddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} + +.panel-group .panel { + margin-bottom: 0; + overflow: hidden; + border-radius: 4px; +} + +.panel-group .panel + .panel { + margin-top: 5px; +} + +.panel-group .panel-heading { + border-bottom: 0; +} + +.panel-group .panel-heading + .panel-collapse .panel-body { + border-top: 1px solid #dddddd; +} + +.panel-group .panel-footer { + border-top: 0; +} + +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #dddddd; +} + +.panel-default { + border-color: #dddddd; +} + +.panel-default > .panel-heading { + color: #333333; + background-color: #f5f5f5; + border-color: #dddddd; +} + +.panel-default > .panel-heading + .panel-collapse .panel-body { + border-top-color: #dddddd; +} + +.panel-default > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #dddddd; +} + +.panel-primary { + border-color: #428bca; +} + +.panel-primary > .panel-heading { + color: #ffffff; + background-color: #428bca; + border-color: #428bca; +} + +.panel-primary > .panel-heading + .panel-collapse .panel-body { + border-top-color: #428bca; +} + +.panel-primary > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #428bca; +} + +.panel-success { + border-color: #d6e9c6; +} + +.panel-success > .panel-heading { + color: #468847; + background-color: #dff0d8; + border-color: #d6e9c6; +} + +.panel-success > .panel-heading + .panel-collapse .panel-body { + border-top-color: #d6e9c6; +} + +.panel-success > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #d6e9c6; +} + +.panel-warning { + border-color: #fbeed5; +} + +.panel-warning > .panel-heading { + color: #c09853; + background-color: #fcf8e3; + border-color: #fbeed5; +} + +.panel-warning > .panel-heading + .panel-collapse .panel-body { + border-top-color: #fbeed5; +} + +.panel-warning > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #fbeed5; +} + +.panel-danger { + border-color: #eed3d7; +} + +.panel-danger > .panel-heading { + color: #b94a48; + background-color: #f2dede; + border-color: #eed3d7; +} + +.panel-danger > .panel-heading + .panel-collapse .panel-body { + border-top-color: #eed3d7; +} + +.panel-danger > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #eed3d7; +} + +.panel-info { + border-color: #bce8f1; +} + +.panel-info > .panel-heading { + color: #3a87ad; + background-color: #d9edf7; + border-color: #bce8f1; +} + +.panel-info > .panel-heading + .panel-collapse .panel-body { + border-top-color: #bce8f1; +} + +.panel-info > .panel-footer + .panel-collapse .panel-body { + border-bottom-color: #bce8f1; +} + +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05); +} + +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, 0.15); +} + +.well-lg { + padding: 24px; + border-radius: 6px; +} + +.well-sm { + padding: 9px; + border-radius: 3px; +} + +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000000; + text-shadow: 0 1px 0 #ffffff; + opacity: 0.2; + filter: alpha(opacity=20); +} + +.close:hover, +.close:focus { + color: #000000; + text-decoration: none; + cursor: pointer; + opacity: 0.5; + filter: alpha(opacity=50); +} + +button.close { + padding: 0; + cursor: pointer; + background: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +body.modal-open, +.modal-open .navbar-fixed-top, +.modal-open .navbar-fixed-bottom { + margin-right: 15px; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + display: none; + overflow: auto; + overflow-y: scroll; +} + +.modal.fade .modal-dialog { + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); + -webkit-transition: -webkit-transform 0.3s ease-out; + -moz-transition: -moz-transform 0.3s ease-out; + -o-transition: -o-transform 0.3s ease-out; + transition: transform 0.3s ease-out; +} + +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); +} + +.modal-dialog { + z-index: 1050; + width: auto; + padding: 10px; + margin-right: auto; + margin-left: auto; +} + +.modal-content { + position: relative; + background-color: #ffffff; + border: 1px solid #999999; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5); + background-clip: padding-box; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; + background-color: #000000; +} + +.modal-backdrop.fade { + opacity: 0; + filter: alpha(opacity=0); +} + +.modal-backdrop.in { + opacity: 0.5; + filter: alpha(opacity=50); +} + +.modal-header { + min-height: 16.428571429px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} + +.modal-header .close { + margin-top: -2px; +} + +.modal-title { + margin: 0; + line-height: 1.428571429; +} + +.modal-body { + position: relative; + padding: 20px; +} + +.modal-footer { + padding: 19px 20px 20px; + margin-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} + +.modal-footer:after { + clear: both; +} + +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} + +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} + +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} + +@media screen and (min-width: 768px) { + .modal-dialog { + right: auto; + left: 50%; + width: 600px; + padding-top: 30px; + padding-bottom: 30px; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5); + } +} + +.tooltip { + position: absolute; + z-index: 1030; + display: block; + font-size: 12px; + line-height: 1.4; + opacity: 0; + filter: alpha(opacity=0); + visibility: visible; +} + +.tooltip.in { + opacity: 0.9; + filter: alpha(opacity=90); +} + +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} + +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} + +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} + +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} + +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #ffffff; + text-align: center; + text-decoration: none; + background-color: #000000; + border-radius: 4px; +} + +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.top-left .tooltip-arrow { + bottom: 0; + left: 5px; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.top-right .tooltip-arrow { + right: 5px; + bottom: 0; + border-top-color: #000000; + border-width: 5px 5px 0; +} + +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-right-color: #000000; + border-width: 5px 5px 5px 0; +} + +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-left-color: #000000; + border-width: 5px 0 5px 5px; +} + +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.tooltip.bottom-left .tooltip-arrow { + top: 0; + left: 5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.tooltip.bottom-right .tooltip-arrow { + top: 0; + right: 5px; + border-bottom-color: #000000; + border-width: 0 5px 5px; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #ffffff; + border: 1px solid #cccccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); + background-clip: padding-box; +} + +.popover.top { + margin-top: -10px; +} + +.popover.right { + margin-left: 10px; +} + +.popover.bottom { + margin-top: 10px; +} + +.popover.left { + margin-left: -10px; +} + +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} + +.popover-content { + padding: 9px 14px; +} + +.popover .arrow, +.popover .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} + +.popover .arrow { + border-width: 11px; +} + +.popover .arrow:after { + border-width: 10px; + content: ""; +} + +.popover.top .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999999; + border-top-color: rgba(0, 0, 0, 0.25); + border-bottom-width: 0; +} + +.popover.top .arrow:after { + bottom: 1px; + margin-left: -10px; + border-top-color: #ffffff; + border-bottom-width: 0; + content: " "; +} + +.popover.right .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999999; + border-right-color: rgba(0, 0, 0, 0.25); + border-left-width: 0; +} + +.popover.right .arrow:after { + bottom: -10px; + left: 1px; + border-right-color: #ffffff; + border-left-width: 0; + content: " "; +} + +.popover.bottom .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-bottom-color: #999999; + border-bottom-color: rgba(0, 0, 0, 0.25); + border-top-width: 0; +} + +.popover.bottom .arrow:after { + top: 1px; + margin-left: -10px; + border-bottom-color: #ffffff; + border-top-width: 0; + content: " "; +} + +.popover.left .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-left-color: #999999; + border-left-color: rgba(0, 0, 0, 0.25); + border-right-width: 0; +} + +.popover.left .arrow:after { + right: 1px; + bottom: -10px; + border-left-color: #ffffff; + border-right-width: 0; + content: " "; +} + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: 0.6s ease-in-out left; + transition: 0.6s ease-in-out left; +} + +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + height: auto; + max-width: 100%; + line-height: 1; +} + +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} + +.carousel-inner > .active { + left: 0; +} + +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} + +.carousel-inner > .next { + left: 100%; +} + +.carousel-inner > .prev { + left: -100%; +} + +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} + +.carousel-inner > .active.left { + left: -100%; +} + +.carousel-inner > .active.right { + left: 100%; +} + +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); + opacity: 0.5; + filter: alpha(opacity=50); +} + +.carousel-control.left { + background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); +} + +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5))); + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%)); + background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); + background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%); + background-repeat: repeat-x; + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); +} + +.carousel-control:hover, +.carousel-control:focus { + color: #ffffff; + text-decoration: none; + opacity: 0.9; + filter: alpha(opacity=90); +} + +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + left: 50%; + z-index: 5; + display: inline-block; +} + +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; +} + +.carousel-control .icon-prev:before { + content: '\2039'; +} + +.carousel-control .icon-next:before { + content: '\203a'; +} + +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} + +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + border: 1px solid #ffffff; + border-radius: 10px; +} + +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #ffffff; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #ffffff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); +} + +.carousel-caption .btn { + text-shadow: none; +} + +@media screen and (min-width: 768px) { + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} + +.clearfix:before, +.clearfix:after { + display: table; + content: " "; +} + +.clearfix:after { + clear: both; +} + +.pull-right { + float: right !important; +} + +.pull-left { + float: left !important; +} + +.hide { + display: none !important; +} + +.show { + display: block !important; +} + +.invisible { + visibility: hidden; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.affix { + position: fixed; +} + +@-ms-viewport { + width: device-width; +} + +@media screen and (max-width: 400px) { + @-ms-viewport { + width: 320px; + } +} + +.hidden { + display: none !important; + visibility: hidden !important; +} + +.visible-xs { + display: none !important; +} + +tr.visible-xs { + display: none !important; +} + +th.visible-xs, +td.visible-xs { + display: none !important; +} + +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-xs.visible-sm { + display: block !important; + } + tr.visible-xs.visible-sm { + display: table-row !important; + } + th.visible-xs.visible-sm, + td.visible-xs.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-xs.visible-md { + display: block !important; + } + tr.visible-xs.visible-md { + display: table-row !important; + } + th.visible-xs.visible-md, + td.visible-xs.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-xs.visible-lg { + display: block !important; + } + tr.visible-xs.visible-lg { + display: table-row !important; + } + th.visible-xs.visible-lg, + td.visible-xs.visible-lg { + display: table-cell !important; + } +} + +.visible-sm { + display: none !important; +} + +tr.visible-sm { + display: none !important; +} + +th.visible-sm, +td.visible-sm { + display: none !important; +} + +@media (max-width: 767px) { + .visible-sm.visible-xs { + display: block !important; + } + tr.visible-sm.visible-xs { + display: table-row !important; + } + th.visible-sm.visible-xs, + td.visible-sm.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-sm.visible-md { + display: block !important; + } + tr.visible-sm.visible-md { + display: table-row !important; + } + th.visible-sm.visible-md, + td.visible-sm.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-sm.visible-lg { + display: block !important; + } + tr.visible-sm.visible-lg { + display: table-row !important; + } + th.visible-sm.visible-lg, + td.visible-sm.visible-lg { + display: table-cell !important; + } +} + +.visible-md { + display: none !important; +} + +tr.visible-md { + display: none !important; +} + +th.visible-md, +td.visible-md { + display: none !important; +} + +@media (max-width: 767px) { + .visible-md.visible-xs { + display: block !important; + } + tr.visible-md.visible-xs { + display: table-row !important; + } + th.visible-md.visible-xs, + td.visible-md.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-md.visible-sm { + display: block !important; + } + tr.visible-md.visible-sm { + display: table-row !important; + } + th.visible-md.visible-sm, + td.visible-md.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-md.visible-lg { + display: block !important; + } + tr.visible-md.visible-lg { + display: table-row !important; + } + th.visible-md.visible-lg, + td.visible-md.visible-lg { + display: table-cell !important; + } +} + +.visible-lg { + display: none !important; +} + +tr.visible-lg { + display: none !important; +} + +th.visible-lg, +td.visible-lg { + display: none !important; +} + +@media (max-width: 767px) { + .visible-lg.visible-xs { + display: block !important; + } + tr.visible-lg.visible-xs { + display: table-row !important; + } + th.visible-lg.visible-xs, + td.visible-lg.visible-xs { + display: table-cell !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .visible-lg.visible-sm { + display: block !important; + } + tr.visible-lg.visible-sm { + display: table-row !important; + } + th.visible-lg.visible-sm, + td.visible-lg.visible-sm { + display: table-cell !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .visible-lg.visible-md { + display: block !important; + } + tr.visible-lg.visible-md { + display: table-row !important; + } + th.visible-lg.visible-md, + td.visible-lg.visible-md { + display: table-cell !important; + } +} + +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} + +.hidden-xs { + display: block !important; +} + +tr.hidden-xs { + display: table-row !important; +} + +th.hidden-xs, +td.hidden-xs { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } + tr.hidden-xs { + display: none !important; + } + th.hidden-xs, + td.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-xs.hidden-sm { + display: none !important; + } + tr.hidden-xs.hidden-sm { + display: none !important; + } + th.hidden-xs.hidden-sm, + td.hidden-xs.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-xs.hidden-md { + display: none !important; + } + tr.hidden-xs.hidden-md { + display: none !important; + } + th.hidden-xs.hidden-md, + td.hidden-xs.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-xs.hidden-lg { + display: none !important; + } + tr.hidden-xs.hidden-lg { + display: none !important; + } + th.hidden-xs.hidden-lg, + td.hidden-xs.hidden-lg { + display: none !important; + } +} + +.hidden-sm { + display: block !important; +} + +tr.hidden-sm { + display: table-row !important; +} + +th.hidden-sm, +td.hidden-sm { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-sm.hidden-xs { + display: none !important; + } + tr.hidden-sm.hidden-xs { + display: none !important; + } + th.hidden-sm.hidden-xs, + td.hidden-sm.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } + tr.hidden-sm { + display: none !important; + } + th.hidden-sm, + td.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-sm.hidden-md { + display: none !important; + } + tr.hidden-sm.hidden-md { + display: none !important; + } + th.hidden-sm.hidden-md, + td.hidden-sm.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-sm.hidden-lg { + display: none !important; + } + tr.hidden-sm.hidden-lg { + display: none !important; + } + th.hidden-sm.hidden-lg, + td.hidden-sm.hidden-lg { + display: none !important; + } +} + +.hidden-md { + display: block !important; +} + +tr.hidden-md { + display: table-row !important; +} + +th.hidden-md, +td.hidden-md { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-md.hidden-xs { + display: none !important; + } + tr.hidden-md.hidden-xs { + display: none !important; + } + th.hidden-md.hidden-xs, + td.hidden-md.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-md.hidden-sm { + display: none !important; + } + tr.hidden-md.hidden-sm { + display: none !important; + } + th.hidden-md.hidden-sm, + td.hidden-md.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } + tr.hidden-md { + display: none !important; + } + th.hidden-md, + td.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-md.hidden-lg { + display: none !important; + } + tr.hidden-md.hidden-lg { + display: none !important; + } + th.hidden-md.hidden-lg, + td.hidden-md.hidden-lg { + display: none !important; + } +} + +.hidden-lg { + display: block !important; +} + +tr.hidden-lg { + display: table-row !important; +} + +th.hidden-lg, +td.hidden-lg { + display: table-cell !important; +} + +@media (max-width: 767px) { + .hidden-lg.hidden-xs { + display: none !important; + } + tr.hidden-lg.hidden-xs { + display: none !important; + } + th.hidden-lg.hidden-xs, + td.hidden-lg.hidden-xs { + display: none !important; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .hidden-lg.hidden-sm { + display: none !important; + } + tr.hidden-lg.hidden-sm { + display: none !important; + } + th.hidden-lg.hidden-sm, + td.hidden-lg.hidden-sm { + display: none !important; + } +} + +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-lg.hidden-md { + display: none !important; + } + tr.hidden-lg.hidden-md { + display: none !important; + } + th.hidden-lg.hidden-md, + td.hidden-lg.hidden-md { + display: none !important; + } +} + +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } + tr.hidden-lg { + display: none !important; + } + th.hidden-lg, + td.hidden-lg { + display: none !important; + } +} + +.visible-print { + display: none !important; +} + +tr.visible-print { + display: none !important; +} + +th.visible-print, +td.visible-print { + display: none !important; +} + +@media print { + .visible-print { + display: block !important; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } + .hidden-print { + display: none !important; + } + tr.hidden-print { + display: none !important; + } + th.hidden-print, + td.hidden-print { + display: none !important; + } +} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.min.css b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.min.css new file mode 100644 index 0000000000000000000000000000000000000000..a553c4f5e08a72a0d475aac9019fa57754abccb3 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/bootstrap/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v3.0.0 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + *//*! normalize.css v2.1.0 | MIT License | git.io/normalize */article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{margin:.67em 0;font-size:2em}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}hr{height:0;-moz-box-sizing:content-box;box-sizing:content-box}mark{color:#000;background:#ff0}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{padding:.35em .625em .75em;margin:0 2px;border:1px solid #c0c0c0}legend{padding:0;border:0}button,input,select,textarea{margin:0;font-family:inherit;font-size:100%}button,input{line-height:normal}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}button[disabled],html input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{padding:0;box-sizing:border-box}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:2cm .5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}button,input,select[multiple],textarea{background-image:none}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}img{vertical-align:middle}.img-responsive{display:block;height:auto;max-width:100%}.img-rounded{border-radius:6px}.img-thumbnail{display:inline-block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);border:0}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16.099999999999998px;font-weight:200;line-height:1.4}@media(min-width:768px){.lead{font-size:21px}}small{font-size:85%}cite{font-style:normal}.text-muted{color:#999}.text-primary{color:#428bca}.text-warning{color:#c09853}.text-danger{color:#b94a48}.text-success{color:#468847}.text-info{color:#3a87ad}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{margin-top:20px;margin-bottom:10px}h4,h5,h6{margin-top:10px;margin-bottom:10px}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}h1 small,.h1 small{font-size:24px}h2 small,.h2 small{font-size:18px}h3 small,.h3 small,h4 small,.h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:bold}dd{margin-left:0}@media(min-width:768px){.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}.dl-horizontal dd:before,.dl-horizontal dd:after{display:table;content:" "}.dl-horizontal dd:after{clear:both}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25}blockquote p:last-child{margin-bottom:0}blockquote small{display:block;line-height:1.428571429;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:1.428571429}code,pre{font-family:Monaco,Menlo,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;white-space:nowrap;background-color:#f9f2f4;border-radius:4px}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.container:before,.container:after{display:table;content:" "}.container:after{clear:both}.row{margin-right:-15px;margin-left:-15px}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.row:before,.row:after{display:table;content:" "}.row:after{clear:both}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left}.col-xs-1{width:8.333333333333332%}.col-xs-2{width:16.666666666666664%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333333333%}.col-xs-5{width:41.66666666666667%}.col-xs-6{width:50%}.col-xs-7{width:58.333333333333336%}.col-xs-8{width:66.66666666666666%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333333334%}.col-xs-11{width:91.66666666666666%}.col-xs-12{width:100%}@media(min-width:768px){.container{max-width:750px}.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left}.col-sm-1{width:8.333333333333332%}.col-sm-2{width:16.666666666666664%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333333333%}.col-sm-5{width:41.66666666666667%}.col-sm-6{width:50%}.col-sm-7{width:58.333333333333336%}.col-sm-8{width:66.66666666666666%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333333334%}.col-sm-11{width:91.66666666666666%}.col-sm-12{width:100%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-11{left:91.66666666666666%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-11{margin-left:91.66666666666666%}}@media(min-width:992px){.container{max-width:970px}.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left}.col-md-1{width:8.333333333333332%}.col-md-2{width:16.666666666666664%}.col-md-3{width:25%}.col-md-4{width:33.33333333333333%}.col-md-5{width:41.66666666666667%}.col-md-6{width:50%}.col-md-7{width:58.333333333333336%}.col-md-8{width:66.66666666666666%}.col-md-9{width:75%}.col-md-10{width:83.33333333333334%}.col-md-11{width:91.66666666666666%}.col-md-12{width:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.333333333333332%}.col-md-push-2{left:16.666666666666664%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333333333%}.col-md-push-5{left:41.66666666666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.333333333333336%}.col-md-push-8{left:66.66666666666666%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333333334%}.col-md-push-11{left:91.66666666666666%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-11{right:91.66666666666666%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-11{margin-left:91.66666666666666%}}@media(min-width:1200px){.container{max-width:1170px}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left}.col-lg-1{width:8.333333333333332%}.col-lg-2{width:16.666666666666664%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333333333%}.col-lg-5{width:41.66666666666667%}.col-lg-6{width:50%}.col-lg-7{width:58.333333333333336%}.col-lg-8{width:66.66666666666666%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333333334%}.col-lg-11{width:91.66666666666666%}.col-lg-12{width:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-11{left:91.66666666666666%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-11{margin-left:91.66666666666666%}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table thead>tr>th,.table tbody>tr>th,.table tfoot>tr>th,.table thead>tr>td,.table tbody>tr>td,.table tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table caption+thead tr:first-child th,.table colgroup+thead tr:first-child th,.table thead:first-child tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed thead>tr>th,.table-condensed tbody>tr>th,.table-condensed tfoot>tr>th,.table-condensed thead>tr>td,.table-condensed tbody>tr>td,.table-condensed tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-child(odd)>td,.table-striped>tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover>tbody>tr:hover>td,.table-hover>tbody>tr:hover>th{background-color:#f5f5f5}table col[class*="col-"]{display:table-column;float:none}table td[class*="col-"],table th[class*="col-"]{display:table-cell;float:none}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8;border-color:#d6e9c6}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td{background-color:#d0e9c6;border-color:#c9e2b3}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede;border-color:#eed3d7}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td{background-color:#ebcccc;border-color:#e6c1c7}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3;border-color:#fbeed5}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td{background-color:#faf2cc;border-color:#f8e5be}@media(max-width:768px){.table-responsive{width:100%;margin-bottom:15px;overflow-x:scroll;overflow-y:hidden;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0;background-color:#fff}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>thead>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>thead>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:bold}input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type="file"]{display:block}select[multiple],select[size]{height:auto}select optgroup{font-family:inherit;font-size:inherit;font-style:inherit}input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(102,175,233,0.6)}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee}textarea.form-control{height:auto}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;padding-left:20px;margin-top:10px;margin-bottom:10px;vertical-align:middle}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;font-weight:normal;vertical-align:middle;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm{height:auto}.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:45px;line-height:45px}textarea.input-lg{height:auto}.has-warning .help-block,.has-warning .control-label{color:#c09853}.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.has-warning .input-group-addon{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.has-error .help-block,.has-error .control-label{color:#b94a48}.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.has-error .input-group-addon{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.has-success .help-block,.has-success .control-label{color:#468847}.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.has-success .input-group-addon{color:#468847;background-color:#dff0d8;border-color:#468847}.form-control-static{padding-top:7px;margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media(min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block}.form-inline .radio,.form-inline .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}.form-horizontal .form-group:before,.form-horizontal .form-group:after{display:table;content:" "}.form-horizontal .form-group:after{clear:both}@media(min-width:768px){.form-horizontal .control-label{text-align:right}}.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{pointer-events:none;cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-link{font-weight:normal;color:#428bca;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url('../fonts/glyphicons-halflings-regular.eot');src:url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),url('../fonts/glyphicons-halflings-regular.woff') format('woff'),url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';-webkit-font-smoothing:antialiased;font-style:normal;font-weight:normal;line-height:1}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-print:before{content:"\e045"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-briefcase:before{content:"\1f4bc"}.glyphicon-calendar:before{content:"\1f4c5"}.glyphicon-pushpin:before{content:"\1f4cc"}.glyphicon-paperclip:before{content:"\1f4ce"}.glyphicon-camera:before{content:"\1f4f7"}.glyphicon-lock:before{content:"\1f512"}.glyphicon-bell:before{content:"\1f514"}.glyphicon-bookmark:before{content:"\1f516"}.glyphicon-fire:before{content:"\1f525"}.glyphicon-wrench:before{content:"\1f527"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid #000;border-right:4px solid transparent;border-bottom:0 dotted;border-left:4px solid transparent;content:""}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#fff;text-decoration:none;background-color:#428bca}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#428bca;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0 dotted;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media(min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}}.btn-default .caret{border-top-color:#333}.btn-primary .caret,.btn-success .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret{border-top-color:#fff}.dropup .btn-default .caret{border-bottom-color:#333}.dropup .btn-primary .caret,.dropup .btn-success .caret,.dropup .btn-warning .caret,.dropup .btn-danger .caret,.dropup .btn-info .caret{border-bottom-color:#fff}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar:before,.btn-toolbar:after{display:table;content:" "}.btn-toolbar:after{clear:both}.btn-toolbar .btn-group{float:left}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group,.btn-toolbar>.btn-group+.btn-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:5px 10px;padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,0.125);box-shadow:inset 0 3px 5px rgba(0,0,0,0.125)}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after{display:table;content:" "}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-bottom-left-radius:4px;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child>.btn:last-child,.btn-group-vertical>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;border-collapse:separate;table-layout:fixed}.btn-group-justified .btn{display:table-cell;float:none;width:1%}[data-toggle="buttons"]>.btn>input[type="radio"],[data-toggle="buttons"]>.btn>input[type="checkbox"]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group.col{float:none;padding-right:0;padding-left:0}.input-group .form-control{width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:45px;line-height:45px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:normal;line-height:1;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type="radio"],.input-group-addon input[type="checkbox"]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-4px}.input-group-btn>.btn:hover,.input-group-btn>.btn:active{z-index:2}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav:before,.nav:after{display:table;content:" "}.nav:after{clear:both}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center}@media(min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}}.nav-tabs.nav-justified>li>a{margin-right:0;border-bottom:1px solid #ddd}.nav-tabs.nav-justified>.active>a{border-bottom-color:#fff}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:5px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center}@media(min-width:768px){.nav-justified>li{display:table-cell;width:1%}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-bottom:1px solid #ddd}.nav-tabs-justified>.active>a{border-bottom-color:#fff}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tabbable:before,.tabbable:after{display:table;content:" "}.tabbable:after{clear:both}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.nav .caret{border-top-color:#428bca;border-bottom-color:#428bca}.nav a:hover .caret{border-top-color:#2a6496;border-bottom-color:#2a6496}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;z-index:1000;min-height:50px;margin-bottom:20px;border:1px solid transparent}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}.navbar:before,.navbar:after{display:table;content:" "}.navbar:after{clear:both}@media(min-width:768px){.navbar{border-radius:4px}}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}.navbar-header:before,.navbar-header:after{display:table;content:" "}.navbar-header:after{clear:both}@media(min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,0.1);-webkit-overflow-scrolling:touch}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse:before,.navbar-collapse:after{display:table;content:" "}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media(min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-collapse .navbar-nav.navbar-left:first-child{margin-left:-15px}.navbar-collapse .navbar-nav.navbar-right:last-child{margin-right:-15px}.navbar-collapse .navbar-text:last-child{margin-right:0}}.container>.navbar-header,.container>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media(min-width:768px){.container>.navbar-header,.container>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{border-width:0 0 1px}@media(min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;border-width:0 0 1px}@media(min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;z-index:1030}.navbar-fixed-bottom{bottom:0;margin-bottom:0}.navbar-brand{float:left;padding:15px 15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media(min-width:768px){.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-top:8px;margin-right:15px;margin-bottom:8px;background-color:transparent;border:1px solid transparent;border-radius:4px}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media(min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media(max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media(min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}@media(min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{padding:10px 15px;margin-top:8px;margin-right:-15px;margin-bottom:8px;margin-left:-15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}@media(min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;padding-left:0;margin-top:0;margin-bottom:0}.navbar-form .radio input[type="radio"],.navbar-form .checkbox input[type="checkbox"]{float:none;margin-left:0}}@media(max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media(min-width:768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-nav.pull-right>li>.dropdown-menu,.navbar-nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-text{float:left;margin-top:15px;margin-bottom:15px}@media(min-width:768px){.navbar-text{margin-right:15px;margin-left:15px}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#ccc}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e6e6e6}.navbar-default .navbar-nav>.dropdown>a:hover .caret,.navbar-default .navbar-nav>.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.open>a .caret,.navbar-default .navbar-nav>.open>a:hover .caret,.navbar-default .navbar-nav>.open>a:focus .caret{border-top-color:#555;border-bottom-color:#555}.navbar-default .navbar-nav>.dropdown>a .caret{border-top-color:#777;border-bottom-color:#777}@media(max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.dropdown>a:hover .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-nav>.dropdown>a .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .navbar-nav>.open>a .caret,.navbar-inverse .navbar-nav>.open>a:hover .caret,.navbar-inverse .navbar-nav>.open>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}@media(max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\00a0"}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager:before,.pager:after{display:table;content:" "}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:#808080}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:bold;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;background-color:#999;border-radius:10px}.badge:empty{display:none}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.btn .badge{position:relative;top:-1px}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;font-size:21px;font-weight:200;line-height:2.1428571435;color:inherit;background-color:#eee}.jumbotron h1{line-height:1;color:inherit}.jumbotron p{line-height:1.4}.container .jumbotron{border-radius:6px}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1{font-size:63px}}.thumbnail{display:inline-block;display:block;height:auto;max-width:100%;padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img{display:block;height:auto;max-width:100%}a.thumbnail:hover,a.thumbnail:focus{border-color:#428bca}.thumbnail>img{margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:bold}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#356635}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#2d6987}.alert-warning{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.alert-warning hr{border-top-color:#f8e5be}.alert-warning .alert-link{color:#a47e3c}.alert-danger{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger hr{border-top-color:#e6c1c7}.alert-danger .alert-link{color:#953b39}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.05);box-shadow:0 1px 1px rgba(0,0,0,0.05)}.panel-body{padding:15px}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel-body:before,.panel-body:after{display:table;content:" "}.panel-body:after{clear:both}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0}.panel>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table{margin-bottom:0}.panel>.panel-body+.table{border-top:1px solid #ddd}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group .panel{margin-bottom:0;overflow:hidden;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-warning{border-color:#fbeed5}.panel-warning>.panel-heading{color:#c09853;background-color:#fcf8e3;border-color:#fbeed5}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#fbeed5}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#fbeed5}.panel-danger{border-color:#eed3d7}.panel-danger>.panel-heading{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#eed3d7}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#eed3d7}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:bold;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}body.modal-open,.modal-open .navbar-fixed-top,.modal-open .navbar-fixed-bottom{margin-right:15px}.modal{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;display:none;overflow:auto;overflow-y:scroll}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{z-index:1050;width:auto;padding:10px;margin-right:auto;margin-left:auto}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.2);border-radius:6px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,0.5);box-shadow:0 3px 9px rgba(0,0,0,0.5);background-clip:padding-box}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1030;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{min-height:16.428571429px;padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{padding:19px 20px 20px;margin-top:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer:before,.modal-footer:after{display:table;content:" "}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media screen and (min-width:768px){.modal-dialog{right:auto;left:50%;width:600px;padding-top:30px;padding-bottom:30px}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,0.5);box-shadow:0 5px 15px rgba(0,0,0,0.5)}}.tooltip{position:absolute;z-index:1030;display:block;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.top-right .tooltip-arrow{right:5px;bottom:0;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-bottom-color:#000;border-width:0 5px 5px}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0;content:" "}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0;content:" "}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0;content:" "}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0;content:" "}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;height:auto;max-width:100%;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6);opacity:.5;filter:alpha(opacity=50)}.carousel-control.left{background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.5)),to(rgba(0,0,0,0.0001)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.5) 0),color-stop(rgba(0,0,0,0.0001) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.5) 0,rgba(0,0,0,0.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000',endColorstr='#00000000',GradientType=1)}.carousel-control.right{right:0;left:auto;background-image:-webkit-gradient(linear,0 top,100% top,from(rgba(0,0,0,0.0001)),to(rgba(0,0,0,0.5)));background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,0.0001) 0),color-stop(rgba(0,0,0,0.5) 100%));background-image:-moz-linear-gradient(left,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-image:linear-gradient(to right,rgba(0,0,0,0.0001) 0,rgba(0,0,0,0.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000',endColorstr='#80000000',GradientType=1)}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;left:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,0.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after{display:table;content:" "}.clearfix:after{clear:both}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.affix{position:fixed}@-ms-viewport{width:device-width}@media screen and (max-width:400px){@-ms-viewport{width:320px}}.hidden{display:none!important;visibility:hidden!important}.visible-xs{display:none!important}tr.visible-xs{display:none!important}th.visible-xs,td.visible-xs{display:none!important}@media(max-width:767px){.visible-xs{display:block!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-xs.visible-sm{display:block!important}tr.visible-xs.visible-sm{display:table-row!important}th.visible-xs.visible-sm,td.visible-xs.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-xs.visible-md{display:block!important}tr.visible-xs.visible-md{display:table-row!important}th.visible-xs.visible-md,td.visible-xs.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-xs.visible-lg{display:block!important}tr.visible-xs.visible-lg{display:table-row!important}th.visible-xs.visible-lg,td.visible-xs.visible-lg{display:table-cell!important}}.visible-sm{display:none!important}tr.visible-sm{display:none!important}th.visible-sm,td.visible-sm{display:none!important}@media(max-width:767px){.visible-sm.visible-xs{display:block!important}tr.visible-sm.visible-xs{display:table-row!important}th.visible-sm.visible-xs,td.visible-sm.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-sm{display:block!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-sm.visible-md{display:block!important}tr.visible-sm.visible-md{display:table-row!important}th.visible-sm.visible-md,td.visible-sm.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-sm.visible-lg{display:block!important}tr.visible-sm.visible-lg{display:table-row!important}th.visible-sm.visible-lg,td.visible-sm.visible-lg{display:table-cell!important}}.visible-md{display:none!important}tr.visible-md{display:none!important}th.visible-md,td.visible-md{display:none!important}@media(max-width:767px){.visible-md.visible-xs{display:block!important}tr.visible-md.visible-xs{display:table-row!important}th.visible-md.visible-xs,td.visible-md.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-md.visible-sm{display:block!important}tr.visible-md.visible-sm{display:table-row!important}th.visible-md.visible-sm,td.visible-md.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-md{display:block!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-md.visible-lg{display:block!important}tr.visible-md.visible-lg{display:table-row!important}th.visible-md.visible-lg,td.visible-md.visible-lg{display:table-cell!important}}.visible-lg{display:none!important}tr.visible-lg{display:none!important}th.visible-lg,td.visible-lg{display:none!important}@media(max-width:767px){.visible-lg.visible-xs{display:block!important}tr.visible-lg.visible-xs{display:table-row!important}th.visible-lg.visible-xs,td.visible-lg.visible-xs{display:table-cell!important}}@media(min-width:768px) and (max-width:991px){.visible-lg.visible-sm{display:block!important}tr.visible-lg.visible-sm{display:table-row!important}th.visible-lg.visible-sm,td.visible-lg.visible-sm{display:table-cell!important}}@media(min-width:992px) and (max-width:1199px){.visible-lg.visible-md{display:block!important}tr.visible-lg.visible-md{display:table-row!important}th.visible-lg.visible-md,td.visible-lg.visible-md{display:table-cell!important}}@media(min-width:1200px){.visible-lg{display:block!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}.hidden-xs{display:block!important}tr.hidden-xs{display:table-row!important}th.hidden-xs,td.hidden-xs{display:table-cell!important}@media(max-width:767px){.hidden-xs{display:none!important}tr.hidden-xs{display:none!important}th.hidden-xs,td.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-xs.hidden-sm{display:none!important}tr.hidden-xs.hidden-sm{display:none!important}th.hidden-xs.hidden-sm,td.hidden-xs.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-xs.hidden-md{display:none!important}tr.hidden-xs.hidden-md{display:none!important}th.hidden-xs.hidden-md,td.hidden-xs.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-xs.hidden-lg{display:none!important}tr.hidden-xs.hidden-lg{display:none!important}th.hidden-xs.hidden-lg,td.hidden-xs.hidden-lg{display:none!important}}.hidden-sm{display:block!important}tr.hidden-sm{display:table-row!important}th.hidden-sm,td.hidden-sm{display:table-cell!important}@media(max-width:767px){.hidden-sm.hidden-xs{display:none!important}tr.hidden-sm.hidden-xs{display:none!important}th.hidden-sm.hidden-xs,td.hidden-sm.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}tr.hidden-sm{display:none!important}th.hidden-sm,td.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-sm.hidden-md{display:none!important}tr.hidden-sm.hidden-md{display:none!important}th.hidden-sm.hidden-md,td.hidden-sm.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-sm.hidden-lg{display:none!important}tr.hidden-sm.hidden-lg{display:none!important}th.hidden-sm.hidden-lg,td.hidden-sm.hidden-lg{display:none!important}}.hidden-md{display:block!important}tr.hidden-md{display:table-row!important}th.hidden-md,td.hidden-md{display:table-cell!important}@media(max-width:767px){.hidden-md.hidden-xs{display:none!important}tr.hidden-md.hidden-xs{display:none!important}th.hidden-md.hidden-xs,td.hidden-md.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-md.hidden-sm{display:none!important}tr.hidden-md.hidden-sm{display:none!important}th.hidden-md.hidden-sm,td.hidden-md.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}tr.hidden-md{display:none!important}th.hidden-md,td.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-md.hidden-lg{display:none!important}tr.hidden-md.hidden-lg{display:none!important}th.hidden-md.hidden-lg,td.hidden-md.hidden-lg{display:none!important}}.hidden-lg{display:block!important}tr.hidden-lg{display:table-row!important}th.hidden-lg,td.hidden-lg{display:table-cell!important}@media(max-width:767px){.hidden-lg.hidden-xs{display:none!important}tr.hidden-lg.hidden-xs{display:none!important}th.hidden-lg.hidden-xs,td.hidden-lg.hidden-xs{display:none!important}}@media(min-width:768px) and (max-width:991px){.hidden-lg.hidden-sm{display:none!important}tr.hidden-lg.hidden-sm{display:none!important}th.hidden-lg.hidden-sm,td.hidden-lg.hidden-sm{display:none!important}}@media(min-width:992px) and (max-width:1199px){.hidden-lg.hidden-md{display:none!important}tr.hidden-lg.hidden-md{display:none!important}th.hidden-lg.hidden-md,td.hidden-lg.hidden-md{display:none!important}}@media(min-width:1200px){.hidden-lg{display:none!important}tr.hidden-lg{display:none!important}th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print{display:none!important}tr.visible-print{display:none!important}th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}.hidden-print{display:none!important}tr.hidden-print{display:none!important}th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/bootstrap/dspace-theme.css b/dspace-jspui/src/main/webapp/static/css/bootstrap/dspace-theme.css new file mode 100644 index 0000000000000000000000000000000000000000..13b43324a6d7e197b17873c944d34809a3a04bdf --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/bootstrap/dspace-theme.css @@ -0,0 +1,66 @@ +/** + * 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/ + */ +.banner img {background-color: #FFFFFF;padding:15px;margin:20px;} +.brand {padding-top: 30px;} +.brand h4 {color: #999999} +ol.breadcrumb li {color: white; font-style: italic;} +ol.breadcrumb li a {color: white; font-weight: bold; font-style: normal;} +body.undernavigation {overflow-x: hidden; padding-top: 65px;} +#content {padding-bottom:60px;} +#designedby {padding: 5px;} +#footer_feedback {padding-top: 12px;} +input[type="file"] {display: block;height: auto;} +div.panel-primary div.panel-heading a {color: white;} +/* This magic gets the 16x16 icon to show up.. setting height/width didn't + do it, but adding padding actually made it show up. */ +img.ds-authority-confidence, +span.ds-authority-confidence +{ width: 16px; height: 16px; margin: 5px; background-repeat: no-repeat; + padding: 0px 2px; vertical-align: bottom; color: transparent;} +img.ds-authority-confidence.cf-unset, +span.ds-authority-confidence.cf-unset + { background-image: url(../../../image/authority/bug.png);} +img.ds-authority-confidence.cf-novalue, +span.ds-authority-confidence.cf-novalue + { background-image: url(../../../image/confidence/0-unauthored.gif);} +img.ds-authority-confidence.cf-rejected, +img.ds-authority-confidence.cf-failed, +span.ds-authority-confidence.cf-rejected, +span.ds-authority-confidence.cf-failed + { background-image: url(../../../image/confidence/2-errortriangle.gif); } +img.ds-authority-confidence.cf-notfound, +span.ds-authority-confidence.cf-notfound + { background-image: url(../../../image/confidence/3-thumb1.gif); } +img.ds-authority-confidence.cf-ambiguous, +span.ds-authority-confidence.cf-ambiguous + { background-image: url(../../../image/confidence/4-question.gif); } +img.ds-authority-confidence.cf-uncertain, +span.ds-authority-confidence.cf-uncertain + { background-image: url(../../../image/confidence/5-pinion.gif); } +img.ds-authority-confidence.cf-accepted, +span.ds-authority-confidence.cf-accepted + { background-image: url(../../../image/confidence/6-greencheck.gif); } + +/* hide authority-value inputs in forms */ +input.ds-authority-value { display:none; } + +/** XXX Change to this to get the authority value to show up for debugging: + input.ds-authority-value { display:inline; } +**/ + +/* for edit-item-form lock button */ +input.ds-authority-lock + { vertical-align: bottom; height: 24px; width: 24px; margin-right: 8px; + background-repeat: no-repeat; background-color: transparent; } +input.ds-authority-lock.is-locked + { background-image: url(../../../image/lock24.png); } +input.ds-authority-lock.is-unlocked + { background-image: url(../../../image/unlock24.png); } + +/* field required in submission */ +.label-required:after { content:" *"; } \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.eot b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..87eaa434234e2a984c261e0450a2f4ad837aa7b4 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.eot differ diff --git a/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.svg b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000000000000000000000000000000000000..5fee0685496c143a002985cdfb832dfd3001e6fc --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,228 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="glyphicons_halflingsregular" horiz-adv-x="1200" > +<font-face units-per-em="1200" ascent="960" descent="-240" /> +<missing-glyph horiz-adv-x="500" /> +<glyph /> +<glyph /> +<glyph unicode=" " /> +<glyph unicode="*" d="M1100 500h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200z" /> +<glyph unicode="+" d="M1100 400h-400v-400h-300v400h-400v300h400v400h300v-400h400v-300z" /> +<glyph unicode=" " /> +<glyph unicode=" " horiz-adv-x="652" /> +<glyph unicode=" " horiz-adv-x="1304" /> +<glyph unicode=" " horiz-adv-x="652" /> +<glyph unicode=" " horiz-adv-x="1304" /> +<glyph unicode=" " horiz-adv-x="434" /> +<glyph unicode=" " horiz-adv-x="326" /> +<glyph unicode=" " horiz-adv-x="217" /> +<glyph unicode=" " horiz-adv-x="217" /> +<glyph unicode=" " horiz-adv-x="163" /> +<glyph unicode=" " horiz-adv-x="260" /> +<glyph unicode=" " horiz-adv-x="72" /> +<glyph unicode=" " horiz-adv-x="260" /> +<glyph unicode=" " horiz-adv-x="326" /> +<glyph unicode="€" d="M800 500h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257 q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406z" /> +<glyph unicode="−" d="M1100 700h-900v-300h900v300z" /> +<glyph unicode="☁" d="M178 300h750q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57z" /> +<glyph unicode="✉" d="M1200 1100h-1200l600 -603zM300 600l-300 -300v600zM1200 900v-600l-300 300zM800 500l400 -400h-1200l400 400l200 -200z" /> +<glyph unicode="✏" d="M1101 889l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13l-94 -97zM401 189l614 614l-214 214l-614 -614zM-13 -13l333 112l-223 223z" /> +<glyph unicode="" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="" d="M700 100h300v-100h-800v100h300v550l-500 550h1200l-500 -550v-550z" /> +<glyph unicode="" d="M1000 934v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q17 -55 85.5 -75.5t147.5 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7q-79 -25 -122.5 -82t-25.5 -112t86 -75.5t147 5.5 q65 21 109 69t44 90v606z" /> +<glyph unicode="" d="M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" /> +<glyph unicode="" d="M649 949q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5t-94 124.5t-33.5 117.5q0 64 28 123t73 100.5t104.5 64t119 20.5 t120 -38.5t104.5 -104.5z" /> +<glyph unicode="" d="M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM168 71l2 1z" /> +<glyph unicode="" d="M791 522l145 -449l-384 275l-382 -275l146 447l-388 280h479l146 400h2l146 -400h472zM747 331l-74 229l193 140h-235l-77 211l-78 -211h-239l196 -142l-73 -226l192 140zM168 71l2 1z" /> +<glyph unicode="" d="M1200 143v-143h-1200v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100z" /> +<glyph unicode="" d="M1200 1100v-1100h-1200v1100h1200zM200 1000h-100v-100h100v100zM900 1000h-600v-400h600v400zM1100 1000h-100v-100h100v100zM200 800h-100v-100h100v100zM1100 800h-100v-100h100v100zM200 600h-100v-100h100v100zM1100 600h-100v-100h100v100zM900 500h-600v-400h600 v400zM200 400h-100v-100h100v100zM1100 400h-100v-100h100v100zM200 200h-100v-100h100v100zM1100 200h-100v-100h100v100z" /> +<glyph unicode="" d="M500 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400 q21 0 35.5 -14.5t14.5 -35.5zM500 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5zM1100 450v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5zM1100 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM300 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1100 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM300 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM700 250v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1100 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5 t14.5 -35.5z" /> +<glyph unicode="" d="M300 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1200 1050v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h700 q21 0 35.5 -14.5t14.5 -35.5zM300 450v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-200q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM1200 650v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5zM300 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5zM1200 250v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M448 34l818 820l-212 212l-607 -607l-206 207l-212 -212z" /> +<glyph unicode="" d="M882 106l-282 282l-282 -282l-212 212l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282z" /> +<glyph unicode="" d="M913 432l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -142 -78 -261zM507 363q137 0 233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5t-234 -97t-97 -233 t97 -233t234 -97zM600 800h100v-200h-100v-100h-200v100h-100v200h100v100h200v-100z" /> +<glyph unicode="" d="M913 432l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 299q-120 -77 -261 -77q-200 0 -342 142t-142 342t142 342t342 142t342 -142t142 -342q0 -141 -78 -262zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 801v-200h400v200h-400z" /> +<glyph unicode="" d="M700 750v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5zM800 975v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123 t-123 184t-45.5 224.5q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155z" /> +<glyph unicode="" d="M1200 1h-200v1200h200v-1200zM900 1h-200v800h200v-800zM600 1h-200v500h200v-500zM300 301h-200v-300h200v300z" /> +<glyph unicode="" d="M488 183l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5 q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39zM600 815q89 0 152 -63 t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152q0 88 63 151t152 63z" /> +<glyph unicode="" d="M900 1100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100zM800 1100v100h-300v-100h300zM200 900h900v-800q0 -41 -29.5 -71 t-70.5 -30h-700q-41 0 -70.5 30t-29.5 71v800zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" /> +<glyph unicode="" d="M1301 601h-200v-600h-300v400h-300v-400h-300v600h-200l656 644z" /> +<glyph unicode="" d="M600 700h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18v1150q0 11 7 18t18 7h475v-500zM1000 800h-300v300z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 600h200 v-100h-300v400h100v-300z" /> +<glyph unicode="" d="M721 400h-242l-40 -400h-539l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538zM712 500l-27 300h-170l-27 -300h224z" /> +<glyph unicode="" d="M1100 400v-400h-1100v400h490l-290 300h200v500h300v-500h200l-290 -300h490zM988 300h-175v-100h175v100z" /> +<glyph unicode="" d="M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 1012q-170 0 -291 -121t-121 -291t121 -291t291 -121t291 121 t121 291t-121 291t-291 121zM700 600h150l-250 -300l-250 300h150v300h200v-300z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM850 600h-150 v-300h-200v300h-150l250 300z" /> +<glyph unicode="" d="M0 500l200 700h800q199 -700 200 -700v-475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18v475zM903 1000h-606l-97 -500h200l50 -200h300l50 200h200z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM797 598 l-297 -201v401z" /> +<glyph unicode="" d="M1177 600h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123t-123 -184t-45.5 -224.5t45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123 t123 184t45.5 224.5z" /> +<glyph unicode="" d="M700 800l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400zM500 400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122l-145 -145v400h400z" /> +<glyph unicode="" d="M100 1200v-1200h1100v1200h-1100zM1100 100h-900v900h900v-900zM400 800h-100v100h100v-100zM1000 800h-500v100h500v-100zM400 600h-100v100h100v-100zM1000 600h-500v100h500v-100zM400 400h-100v100h100v-100zM1000 400h-500v100h500v-100zM400 200h-100v100h100v-100 zM1000 300h-500v-100h500v100z" /> +<glyph unicode="" d="M200 0h-100v1100h100v-1100zM1100 600v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5z" /> +<glyph unicode="" d="M1200 275v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5t-49.5 -227v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50 q11 0 18 7t7 18zM400 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14zM1000 480v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14z" /> +<glyph unicode="" d="M0 800v-400h300l300 -200v800l-300 -200h-300zM971 600l141 -141l-71 -71l-141 141l-141 -141l-71 71l141 141l-141 141l71 71l141 -141l141 141l71 -71z" /> +<glyph unicode="" d="M0 800v-400h300l300 -200v800l-300 -200h-300zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" /> +<glyph unicode="" d="M974 186l6 8q142 178 142 405q0 230 -144 408l-6 8l-83 -64l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8zM300 801l300 200v-800l-300 200h-300v400h300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257z" /> +<glyph unicode="" d="M100 700h400v100h100v100h-100v300h-500v-600h100v100zM1200 700v500h-600v-200h100v-300h200v-300h300v200h-200v100h200zM100 1100h300v-300h-300v300zM800 800v300h300v-300h-300zM200 900h100v100h-100v-100zM900 1000h100v-100h-100v100zM300 600h-100v-100h-200 v-500h500v500h-200v100zM900 200v-100h-200v100h-100v100h100v200h-200v100h300v-300h200v-100h-100zM400 400v-300h-300v300h300zM300 200h-100v100h100v-100zM1100 300h100v-100h-100v100zM600 100h100v-100h-100v100zM1200 100v-100h-300v100h300z" /> +<glyph unicode="" d="M100 1200h-100v-1000h100v1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 1200v-1000h-200v1000h200zM400 100v-100h-300v100h300zM500 91h100v-91h-100v91zM700 91h100v-91h-100v91zM1100 91v-91h-200v91h200z " /> +<glyph unicode="" d="M1200 500l-500 -500l-699 700v475q0 10 7.5 17.5t17.5 7.5h474zM320 882q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71t29 -71q30 -30 71.5 -30t71.5 30z" /> +<glyph unicode="" d="M1201 500l-500 -500l-699 700v475q0 11 7 18t18 7h474zM1501 500l-500 -500l-50 50l450 450l-700 700h100zM320 882q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71t30 -71q29 -30 71 -30t71 30z" /> +<glyph unicode="" d="M1200 1200v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900v1025l175 175h925z" /> +<glyph unicode="" d="M947 829l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18l-94 -346l40 -124h592zM1200 800v-700h-200v200h-800v-200h-200v700h200l100 -200h600l100 200h200zM881 176l38 -152q2 -10 -3.5 -17t-15.5 -7h-600q-10 0 -15.5 7t-3.5 17l38 152q2 10 11.5 17t19.5 7 h500q10 0 19.5 -7t11.5 -17z" /> +<glyph unicode="" d="M1200 0v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417zM416 521l178 457l46 -140l116 -317 h-340z" /> +<glyph unicode="" d="M100 1199h471q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111t-162 -38.5h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21 t-29 14t-49 14.5v70zM400 1079v-379h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400z" /> +<glyph unicode="" d="M877 1200l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425z" /> +<glyph unicode="" d="M1150 1200h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49v300h150h700zM100 1000v-800h75l-125 -167l-125 167h75v800h-75l125 167 l125 -167h-75z" /> +<glyph unicode="" d="M950 1201h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50v300h150h700zM200 101h800v75l167 -125l-167 -125v75h-800v-75l-167 125l167 125 v-75z" /> +<glyph unicode="" d="M700 950v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35zM1100 650v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1000 q21 0 35.5 15t14.5 35zM900 350v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35 t35.5 -15h1100q21 0 35.5 15t14.5 35z" /> +<glyph unicode="" d="M1000 950v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 650v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h1100 q21 0 35.5 15t14.5 35zM1000 350v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35zM1200 50v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35 t35.5 -15h1100q21 0 35.5 15t14.5 35z" /> +<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> +<glyph unicode="" d="M0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> +<glyph unicode="" d="M0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35zM0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" /> +<glyph unicode="" d="M400 1100h-100v-1100h100v1100zM700 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM1100 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM100 425v75h-201v100h201v75l166 -125zM900 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM1200 50v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5 v-100q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35z" /> +<glyph unicode="" d="M201 950v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35zM801 1100h100v-1100h-100v1100zM601 650v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15 h500q20 0 35 15t15 35zM1101 425v75h200v100h-200v75l-167 -125zM401 350v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35zM701 50v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5 v-100q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35z" /> +<glyph unicode="" d="M900 925v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53zM1200 300l-300 300l300 300v-600z" /> +<glyph unicode="" d="M1200 1056v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31zM1100 1000h-1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500zM476 750q0 -56 -39 -95t-95 -39t-95 39t-39 95t39 95t95 39t95 -39 t39 -95z" /> +<glyph unicode="" d="M600 1213q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262q0 124 60.5 231.5t165 172t226.5 64.5zM599 514q107 0 182.5 75.5t75.5 182.5t-75.5 182 t-182.5 75t-182 -75.5t-75 -181.5q0 -107 75.5 -182.5t181.5 -75.5z" /> +<glyph unicode="" d="M600 1199q122 0 233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233t47.5 233t127.5 191t191 127.5t233 47.5zM600 173v854q-176 0 -301.5 -125t-125.5 -302t125.5 -302t301.5 -125z " /> +<glyph unicode="" d="M554 1295q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 138.5t-64 210.5q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5zM455 296q-7 6 -18 17 t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156q14 -82 59.5 -136t136.5 -80z" /> +<glyph unicode="" d="M1108 902l113 113l-21 85l-92 28l-113 -113zM1100 625v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125zM436 341l161 50l412 412l-114 113l-405 -405z" /> +<glyph unicode="" d="M1100 453v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5z M813 431l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209z" /> +<glyph unicode="" d="M1100 569v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5h300q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69z M625 348l566 567l-136 137l-430 -431l-147 147l-136 -136z" /> +<glyph unicode="" d="M900 303v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198l-300 300l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296z" /> +<glyph unicode="" d="M900 0l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100z" /> +<glyph unicode="" d="M1200 0l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100z" /> +<glyph unicode="" d="M1200 0l-500 488v-488l-564 550l564 550v-487l500 487v-1100z" /> +<glyph unicode="" d="M1100 550l-900 550v-1100z" /> +<glyph unicode="" d="M500 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM900 150v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -21 14.5 -35.5t35.5 -14.5h200 q21 0 35.5 14.5t14.5 35.5z" /> +<glyph unicode="" d="M1100 150v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35z" /> +<glyph unicode="" d="M500 0v488l-500 -488v1100l500 -487v487l564 -550z" /> +<glyph unicode="" d="M1050 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488l-500 -488v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M650 1064l-550 -564h1100zM1200 350v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M777 7l240 240l-353 353l353 353l-240 240l-592 -594z" /> +<glyph unicode="" d="M513 -46l-241 240l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-200h-200v-200h200v-200h200v200h200v200h-200v200h-200z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM300 700v-200h600v200h-600z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM247 741l141 -141l-142 -141l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141 l-141 142z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM546 623l-102 102l-174 -174l276 -277l411 411l-175 174z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 500h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3 q-105 0 -172 -56t-67 -183h144q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5zM500 400v-100h200v100h-200z" /> +<glyph unicode="" d="M600 1197q162 0 299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5t80 299.5t217.5 217.5t299.5 80zM500 900v-100h200v100h-200zM400 700v-100h100v-200h-100v-100h400v100h-100v300h-300z" /> +<glyph unicode="" d="M1200 700v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194v200h194q15 60 36 104.5t55.5 86t88 69t126.5 40.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203zM700 500v-206q149 48 201 206h-201v200h200 q-25 74 -76 127.5t-124 76.5v-204h-200v203q-75 -24 -130 -77.5t-79 -125.5h209v-200h-210q24 -73 79.5 -127.5t130.5 -78.5v206h200z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM844 735 l-135 -135l135 -135l-109 -109l-135 135l-135 -135l-109 109l135 135l-135 135l109 109l135 -135l135 135z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM896 654 l-346 -345l-228 228l141 141l87 -87l204 205z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM248 385l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5q0 -115 62 -215zM955 809l-564 -564q97 -59 209 -59q171 0 292.5 121.5 t121.5 292.5q0 112 -59 209z" /> +<glyph unicode="" d="M1200 400h-600v-301l-600 448l600 453v-300h600v-300z" /> +<glyph unicode="" d="M600 400h-600v300h600v300l600 -453l-600 -448v301z" /> +<glyph unicode="" d="M1098 600h-298v-600h-300v600h-296l450 600z" /> +<glyph unicode="" d="M998 600l-449 -600l-445 600h296v600h300v-600h298z" /> +<glyph unicode="" d="M600 199v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453z" /> +<glyph unicode="" d="M1200 1200h-400l129 -129l-294 -294l142 -142l294 294l129 -129v400zM565 423l-294 -294l129 -129h-400v400l129 -129l294 294z" /> +<glyph unicode="" d="M871 730l129 -130h-400v400l129 -129l295 295l142 -141zM200 600h400v-400l-129 130l-295 -295l-142 141l295 295z" /> +<glyph unicode="" d="M600 1177q118 0 224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5t45.5 224.5t123 184t184 123t224.5 45.5zM686 549l58 302q4 20 -8 34.5t-33 14.5h-207q-20 0 -32 -14.5t-8 -34.5 l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5zM700 400h-200v-100h200v100z" /> +<glyph unicode="" d="M1200 900h-111v6t-1 15t-3 18l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6h-111v-100h100v-200h400v300h200v-300h400v200h100v100z M731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269zM481 900h-281q-3 0 14 48t35 96l18 47zM100 0h400v400h-400v-400zM700 400h400v-400h-400v400z" /> +<glyph unicode="" d="M0 121l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55l-201 -202 v143zM692 611q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5t86.5 76.5q55 66 367 234z" /> +<glyph unicode="" d="M1261 600l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5 t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30zM600 240q64 0 123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212 q0 85 46 158q-102 -87 -226 -258q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5zM484 762l-107 -106q49 -124 154 -191l105 105q-37 24 -75 72t-57 84z" /> +<glyph unicode="" d="M906 1200l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43l-26 40l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148zM1261 600l-26 -40q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5 t-124 -100t-146.5 -79l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52zM513 264l37 141q-107 18 -178.5 101.5t-71.5 193.5q0 85 46 158q-102 -87 -226 -258q210 -282 393 -336z M484 762l-107 -106q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68z" /> +<glyph unicode="" d="M-47 0h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 33 -48 36t-48 -29l-642 -1066q-21 -32 -7.5 -66t50.5 -34zM700 200v100h-200v-100h-345l445 723l445 -723h-345zM700 700h-200v-100l100 -300l100 300v100z" /> +<glyph unicode="" d="M800 711l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -21 -13 -29t-32 1l-94 78h-222l-94 -78q-19 -9 -32 -1t-13 29v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41q0 20 11 44.5t26 38.5 l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339z" /> +<glyph unicode="" d="M941 800l-600 -600h-341v200h259l600 600h241v198l300 -295l-300 -300v197h-159zM381 678l141 142l-181 180h-341v-200h259zM1100 598l300 -295l-300 -300v197h-241l-181 181l141 142l122 -123h159v198z" /> +<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" /> +<glyph unicode="" d="M400 900h-300v300h300v-300zM1100 900h-300v300h300v-300zM1100 800v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5t-58 109.5t-31.5 116t-15 104t-3 83v200h300v-250q0 -113 6 -145 q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300z" /> +<glyph unicode="" d="M902 184l226 227l-578 579l-580 -579l227 -227l352 353z" /> +<glyph unicode="" d="M650 218l578 579l-226 227l-353 -353l-352 353l-227 -227z" /> +<glyph unicode="" d="M1198 400v600h-796l215 -200h381v-400h-198l299 -283l299 283h-200zM-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196z" /> +<glyph unicode="" d="M1050 1200h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35 q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43l-100 475q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5z" /> +<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" /> +<glyph unicode="" d="M201 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000zM1501 700l-300 -700h-1200l300 700h1200z" /> +<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" /> +<glyph unicode="" d="M900 303v197h-600v-197l-300 297l300 298v-198h600v198l300 -298z" /> +<glyph unicode="" d="M31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM100 300h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM900 200h-100v-100h100v100z M1100 200h-100v-100h100v100z" /> +<glyph unicode="" d="M1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35zM325 800l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35q-56 337 -56 351v250v5 q0 13 0.5 18.5t2.5 13t8 10.5t15 3h200zM-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5z" /> +<glyph unicode="" d="M445 1180l-45 -233l-224 78l78 -225l-233 -44l179 -156l-179 -155l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180z" /> +<glyph unicode="" d="M700 1200h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400q0 -75 100 -75h61q123 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5zM700 925l-50 -225h450 v-125l-250 -375h-214l-136 100h-100v375l150 212l100 213h50v-175zM0 800v-600h200v600h-200z" /> +<glyph unicode="" d="M700 0h-50q-27 0 -51 20t-38 48l-96 198l-145 196q-20 26 -20 63v400q0 75 100 75h61q123 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5zM200 400h-200v600h200 v-600zM700 275l-50 225h450v125l-250 375h-214l-136 -100h-100v-375l150 -212l100 -213h50v175z" /> +<glyph unicode="" d="M364 873l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM408 792v-503 l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83zM208 200h-200v600h200v-600z" /> +<glyph unicode="" d="M475 1104l365 -230q7 -4 16.5 -10.5t26 -26t16.5 -36.5v-526q0 -13 -85.5 -93.5t-93.5 -80.5h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-84 0 -139 39t-55 111t54 110t139 37h302l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6zM370 946 l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100h222q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l106 89v502l-342 237zM1199 201h-200v600h200v-600z" /> +<glyph unicode="" d="M1100 473v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90zM911 400h-503l-236 339 l83 86l183 -146q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6v7.5v7v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294zM1000 200v-200h-600v200h600z" /> +<glyph unicode="" d="M305 1104v200h600v-200h-600zM605 310l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15l-230 -362q-15 -31 7 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85l-1 -302q0 -84 38.5 -138t110.5 -54t111 55t39 139v106z M905 804v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146l-83 86l237 339h503z" /> +<glyph unicode="" d="M603 1195q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM598 701h-298v-201h300l-2 -194l402 294l-402 298v-197z" /> +<glyph unicode="" d="M597 1195q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5zM200 600l400 -294v194h302v201h-300v197z" /> +<glyph unicode="" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM300 600h200v-300h200v300h200l-300 400z" /> +<glyph unicode="" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM500 900v-300h-200l300 -400l300 400h-200v300h-200z" /> +<glyph unicode="" d="M603 1195q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5zM627 1101q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6 q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55 t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q102 -2 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7 q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5 t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 41 1 44q31 -13 58.5 -14.5t39.5 3.5l11 4q6 36 -17 53.5t-64 28.5t-56 23q-19 -3 -37 0zM613 994q0 -18 8 -42.5t16.5 -44t9.5 -23.5q-9 2 -31 5t-36 5t-32 8t-30 14q3 12 16 30t16 25q10 -10 18.5 -10 t14 6t14.5 14.5t16 12.5z" /> +<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " /> +<glyph unicode="" d="M1100 1200v-100h-1000v100h1000zM150 1000h900l-350 -500v-300l-200 -200v500z" /> +<glyph unicode="" d="M329 729l142 142l-200 200l129 129h-400v-400l129 129zM1200 1200v-400l-129 129l-200 -200l-142 142l200 200l-129 129h400zM271 129l129 -129h-400v400l129 -129l200 200l142 -142zM1071 271l129 129v-400h-400l129 129l-200 200l142 142z" /> +<glyph unicode="" d="M596 1192q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1010q-171 0 -292.5 -121.5t-121.5 -292.5q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5zM455 905 q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5t16 38.5t39 16.5zM708 821l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5 q0 32 20.5 56.5t51.5 29.5zM855 709q23 0 38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39q0 22 16 38t39 16zM345 709q23 0 39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39t15.5 38.5t38.5 15.5z" /> +<glyph unicode="" d="M649 54l-16 22q-90 125 -293 323q-71 70 -104.5 105.5t-77 89.5t-61 99t-17.5 91q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-203 -198 -293 -323zM844 524l12 12 q64 62 97.5 97t64.5 79t31 72q0 71 -48 119t-105 48q-74 0 -132 -82l-118 -171l-114 174q-51 79 -123 79q-60 0 -109.5 -49t-49.5 -118q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203z" /> +<glyph unicode="" d="M476 406l19 -17l105 105l-212 212l389 389l247 -247l-95 -96l18 -18q46 -46 77 -99l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159q0 -93 66 -159zM123 193l141 -141q66 -66 159 -66q95 0 159 66 l283 283q66 66 66 159t-66 159l-141 141q-12 12 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159q0 -94 66 -160z" /> +<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM900 1000h-600v-700h600v700zM600 46q43 0 73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5t-73.5 -30.5t-30.5 -73.5 t30.5 -73.5t73.5 -30.5z" /> +<glyph unicode="" d="M700 1029v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5h139q5 -77 48.5 -126.5t117.5 -64.5v335l-27 7q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5 t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5zM600 755v274q-61 -8 -97.5 -37.5t-36.5 -102.5q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3zM700 548 v-311q170 18 170 151q0 64 -44 99.5t-126 60.5z" /> +<glyph unicode="" d="M866 300l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5t-30 142.5h-221v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5 t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -11 2.5 -24.5t5.5 -24t9.5 -26.5t10.5 -25t14 -27.5t14 -25.5t15.5 -27t13.5 -24h242v-100h-197q8 -50 -2.5 -115t-31.5 -94 q-41 -59 -99 -113q35 11 84 18t70 7q32 1 102 -16t104 -17q76 0 136 30z" /> +<glyph unicode="" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1200l298 -300h-198v-900h-200v900h-198z" /> +<glyph unicode="" d="M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-500h-100v100h-100v-100h-100v500h300zM901 1100h-100v-200h100v200zM700 500h300v-200h-99v-100h-100v100h99v100h-200v100zM800 100h200v-100h-300v200h100v-100z" /> +<glyph unicode="" d="M400 300h198l-298 -300l-298 300h198v900h200v-900zM1000 1200v-200h-99v-100h-100v100h99v100h-200v100h300zM800 800h200v-100h-300v200h100v-100zM700 500h300v-500h-100v100h-100v-100h-100v500zM801 200h100v200h-100v-200z" /> +<glyph unicode="" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1100h-100v100h200v-500h-100v400zM1100 500v-500h-100v100h-200v400h300zM1001 400h-100v-200h100v200z" /> +<glyph unicode="" d="M300 0l298 300h-198v900h-200v-900h-198zM1100 1200v-500h-100v100h-200v400h300zM1001 1100h-100v-200h100v200zM900 400h-100v100h200v-500h-100v400z" /> +<glyph unicode="" d="M300 0l298 300h-198v900h-200v-900h-198zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" /> +<glyph unicode="" d="M300 0l298 300h-198v900h-200v-900h-198zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" /> +<glyph unicode="" d="M400 1100h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5v300q0 165 117.5 282.5t282.5 117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5z" /> +<glyph unicode="" d="M700 0h-300q-163 0 -281.5 117.5t-118.5 282.5v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5 t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5zM400 800v-500l333 250z" /> +<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM800 700h-500l250 -333z" /> +<glyph unicode="" d="M1100 700v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5zM900 300v500q0 41 -29.5 70.5t-70.5 29.5h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5 t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5zM550 733l-250 -333h500z" /> +<glyph unicode="" d="M500 1100h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200zM700 550l-400 -350v200h-300v300h300v200z" /> +<glyph unicode="" d="M403 2l9 -1q13 0 26 16l538 630q15 19 6 36q-8 18 -32 16h-300q1 4 78 219.5t79 227.5q2 17 -6 27l-8 8h-9q-16 0 -25 -15q-4 -5 -98.5 -111.5t-228 -257t-209.5 -238.5q-17 -19 -7 -40q10 -19 32 -19h302q-155 -438 -160 -458q-5 -21 4 -32z" /> +<glyph unicode="" d="M800 200h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185zM900 200v200h-300v300h300v200l400 -350z" /> +<glyph unicode="" d="M1200 700l-149 149l-342 -353l-213 213l353 342l-149 149h500v-500zM1022 571l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5v-300 q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM600 794 q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" /> +<glyph unicode="" d="M700 800v400h-300v-400h-300l445 -500l450 500h-295zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" /> +<glyph unicode="" d="M400 700v-300h300v300h295l-445 500l-450 -500h300zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" /> +<glyph unicode="" d="M405 400l596 596l-154 155l-442 -442l-150 151l-155 -155zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" /> +<glyph unicode="" d="M409 1103l-97 97l-212 -212l97 -98zM650 861l-149 149l-212 -212l149 -149l-238 -248h700v699zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" /> +<glyph unicode="" d="M539 950l-149 -149l212 -212l149 148l248 -237v700h-699zM297 709l-97 -97l212 -212l98 97zM25 300h1048q11 0 19 -7.5t8 -17.5v-275h-1100v275q0 11 7 18t18 7zM1000 200h-100v-50h100v50z" /> +<glyph unicode="" d="M1200 1199v-1079l-475 272l-310 -393v416h-392zM1166 1148l-672 -712v-226z" /> +<glyph unicode="" d="M1100 1000v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1200h-100v-200h100v200z" /> +<glyph unicode="" d="M578 500h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120zM700 1200h-100v-200h100v200zM1300 538l-475 -476l-244 244l123 123l120 -120l353 352z" /> +<glyph unicode="" d="M529 500h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170zM700 1200h-100v-200h100v200zM1167 6l-170 170l-170 -170l-127 127l170 170l-170 170l127 127l170 -170l170 170l127 -128 l-170 -169l170 -170z" /> +<glyph unicode="" d="M700 500h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200zM700 1000h-100v200h100v-200zM1000 600h-200v-300h-200l300 -300l300 300h-200v300z" /> +<glyph unicode="" d="M602 500h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200zM700 1000h-100v200h100v-200zM1000 300h200l-300 300l-300 -300h200v-300h200v300z" /> +<glyph unicode="" d="M1200 900v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1200zM0 800v-550q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200zM100 500h400v-200h-400v200z" /> +<glyph unicode="" d="M500 1000h400v198l300 -298l-300 -298v198h-400v200zM100 800v200h100v-200h-100zM400 800h-100v200h100v-200zM700 300h-400v-198l-300 298l300 298v-198h400v-200zM800 500h100v-200h-100v200zM1000 500v-200h100v200h-100z" /> +<glyph unicode="" d="M1200 50v1106q0 31 -18 40.5t-44 -7.5l-276 -117q-25 -16 -43.5 -50.5t-18.5 -65.5v-359q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5zM550 1200l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447l-100 203v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300z" /> +<glyph unicode="" d="M1100 106v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394 q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5z" /> +<glyph unicode="" d="M675 1000l-100 100h-375l-100 -100h400l200 -200v-98l295 98h105v200h-425zM500 300v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5zM100 800h300v-200h-300v200zM700 565l400 133 v-163l-400 -133v163zM100 500h300v-200h-300v200zM805 300l295 98v-298h-425l-100 -100h-375l-100 100h400l200 200h105z" /> +<glyph unicode="" d="M179 1169l-162 -162q-1 -11 -0.5 -32.5t16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q16 17 13 40.5t-22 37.5l-192 136q-19 14 -45 12t-42 -19l-119 -118q-143 103 -267 227q-126 126 -227 268l118 118 q17 17 20 41.5t-11 44.5l-139 194q-14 19 -36.5 22t-40.5 -14z" /> +<glyph unicode="" d="M1200 712v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40t-53.5 -36.5t-31 -27.5l-9 -10v-200q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38 t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5zM800 650l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -15 -35.5t-35 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5 t30 -27.5t12 -24l1 -10v-50z" /> +<glyph unicode="" d="M175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250zM1200 100v-100h-1100v100h1100z" /> +<glyph unicode="" d="M600 1100h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300v1000q0 41 29.5 70.5t70.5 29.5zM1000 800h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300v700q0 41 29.5 70.5t70.5 29.5zM400 0v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400h300z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM400 600h-100v200h-100v-500h100v200h100v-200h100v500h-100v-200zM800 800h-200v-500h200v100h100v300h-100 v100zM800 700v-300h-100v300h100z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-500h300v100h-200v300h200v100h-300zM600 800v-500h300v100h-200v300h200v100h-300z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM500 700l-300 -150l300 -150v300zM600 400l300 150l-300 150v-300z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM900 800v-500h-700v500h700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM800 700h-130 q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM200 800v-300h200v-100h-200v-100h300v300h-200v100h200v100h-300zM800 300h100v500h-200v-100h100v-400z M601 300h100v100h-100v-100z" /> +<glyph unicode="" d="M1200 800v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212zM1000 900h-900v-700h900v700zM300 700v100h-100v-500h300v400h-200zM800 300h100v500h-200v-100h100v-400zM401 400h-100v200h100v-200z M601 300h100v100h-100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM1000 900h-900v-700h900v700zM400 700h-200v100h300v-300h-99v-100h-100v100h99v200zM800 700h-100v100h200v-500h-100v400zM201 400h100v-100 h-100v100zM701 300h-100v100h100v-100z" /> +<glyph unicode="" d="M600 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM600 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700h-300 v-200h300v-100h-300l-100 100v200l100 100h300v-100z" /> +<glyph unicode="" d="M596 1196q162 0 299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299t80 299t217 217t299 80zM596 1014q-171 0 -292.5 -121.5t-121.5 -292.5t121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5zM800 700v-100 h-100v100h-200v-100h200v-100h-200v-100h-100v400h300zM800 400h-100v100h100v-100z" /> +<glyph unicode="" d="M800 300h128q120 0 205 86t85 208q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h222v300h400v-300zM700 200h200l-300 -300 l-300 300h200v300h200v-300z" /> +<glyph unicode="" d="M600 714l403 -403q94 26 154.5 104t60.5 178q0 121 -85 207.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5q0 -80 56.5 -137t135.5 -57h8zM700 -100h-200v300h-200l300 300 l300 -300h-200v-300z" /> +<glyph unicode="" d="M700 200h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-155l-75 -45h350l-75 45v155z" /> +<glyph unicode="" d="M700 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -12t1 -11q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5 q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350z" /> +<glyph unicode="💼" d="M800 1000h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100zM500 1000h200v100h-200v-100zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" /> +<glyph unicode="📅" d="M1100 900v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150h1100zM0 800v-750q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100zM100 600h100v-100h-100v100zM300 600h100v-100h-100v100z M500 600h100v-100h-100v100zM700 600h100v-100h-100v100zM900 600h100v-100h-100v100zM100 400h100v-100h-100v100zM300 400h100v-100h-100v100zM500 400h100v-100h-100v100zM700 400h100v-100h-100v100zM900 400h100v-100h-100v100zM100 200h100v-100h-100v100zM300 200 h100v-100h-100v100zM500 200h100v-100h-100v100zM700 200h100v-100h-100v100zM900 200h100v-100h-100v100z" /> +<glyph unicode="📌" d="M902 1185l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207l-380 -303l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15z" /> +<glyph unicode="📎" d="M518 119l69 -60l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163t35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84 t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -79.5 -17t-67.5 -51l-388 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348 q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256z" /> +<glyph unicode="📷" d="M1200 200v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5z M1000 700h-100v100h100v-100zM844 500q0 -100 -72 -172t-172 -72t-172 72t-72 172t72 172t172 72t172 -72t72 -172zM706 500q0 44 -31 75t-75 31t-75 -31t-31 -75t31 -75t75 -31t75 31t31 75z" /> +<glyph unicode="🔒" d="M900 800h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" /> +<glyph unicode="🔔" d="M1062 400h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-22 -9 -63 -23t-167.5 -37t-251.5 -23t-245.5 20.5t-178.5 41.5l-58 20q-18 7 -31 27.5t-13 40.5q0 21 13.5 35.5t33.5 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94 q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327zM600 104q-54 0 -103 6q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6z" /> +<glyph unicode="🔖" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" /> +<glyph unicode="🔥" d="M400 755q2 -12 8 -41.5t8 -43t6 -39.5t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85t5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5 q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129 q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5z" /> +<glyph unicode="🔧" d="M948 778l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138z" /> +</font> +</defs></svg> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.ttf b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..be784dc1d5bcb92ab155f578f3723524a3dd9688 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.ttf differ diff --git a/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.woff b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..2cc3e4852a5a42e6aadd6284e067b66e14a57bc7 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/fonts/glyphicons-halflings-regular.woff differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/animated-overlay.gif b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/animated-overlay.gif new file mode 100644 index 0000000000000000000000000000000000000000..d441f75ebfbdf26a265dfccd670120d25c0a341c Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/animated-overlay.gif differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..81f996dac89b3b7b1a5e835ce164acd27d7ae4ee Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_55_fbec88_40x100.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_55_fbec88_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..b3d250dde9b5d328bf86ab03a5ccd388e28f140c Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_flat_55_fbec88_40x100.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..f60d88dd6d201c21927caf4a598eee1d59bed5d3 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_85_dfeffc_1x400.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_85_dfeffc_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..3d7b92d1e291ecd7bcdfa0510b01c5de420ed0f8 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_85_dfeffc_1x400.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_95_fef1ec_1x400.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..20eb6cab098981e24fdf0355889964af5ec6e1df Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png new file mode 100644 index 0000000000000000000000000000000000000000..80acaa822934da0f183c11504dc8f843214a0b98 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ae7942b14abc2407ef1a74f66edbf600dcc91b99 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png new file mode 100644 index 0000000000000000000000000000000000000000..9bc578b6eb9aff4d1ad180cbcbcf00e4ec89831c Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_217bc0_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_217bc0_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..8d2b7e57044465bac0008ff88d23cdebeab6a8b8 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_217bc0_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_2e83ff_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..84b601bf0f726bf95801da487deaf2344a32e4b8 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_2e83ff_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_469bdd_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_469bdd_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..5dff3f962cd744033b2aef575491451a8b2ce6a8 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_469bdd_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_6da8d5_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_6da8d5_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..f7809f8566cd0aaef9af00e7caeca9d3720cf1b0 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_6da8d5_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_cd0a0a_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5b6b0930f672fa08e9b9bdbe5e55370fd1dc30 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_cd0a0a_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_d8e7f3_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_d8e7f3_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..9b46228fb1e80406b2a9a65b694e5674494c2775 Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_d8e7f3_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_f9bd01_256x240.png b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_f9bd01_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..f1f0531ad5b02b7f891d84a6b6db6ce7290b65de Binary files /dev/null and b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/images/ui-icons_f9bd01_256x240.png differ diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.css b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.css new file mode 100644 index 0000000000000000000000000000000000000000..b251e3c6b837dab040d61e4fc8adf68e10218fa4 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.css @@ -0,0 +1,1177 @@ +/*! jQuery UI - v1.10.3 - 2013-08-25 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-clearfix { + min-height: 0; /* support: IE7 */ +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + filter:Alpha(Opacity=0); +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; +} + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin-top: 2px; + padding: .5em .5em .5em .7em; + min-height: 0; /* support: IE7 */ +} +.ui-accordion .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-noicons { + padding-left: .7em; +} +.ui-accordion .ui-accordion-icons .ui-accordion-icons { + padding-left: 2.2em; +} +.ui-accordion .ui-accordion-header .ui-accordion-header-icon { + position: absolute; + left: .5em; + top: 50%; + margin-top: -8px; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-button { + display: inline-block; + position: relative; + padding: 0; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + overflow: visible; /* removes extra width in IE */ +} +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2.2em; +} +/* button elements seem to need a little more width */ +button.ui-button-icon-only { + width: 2.4em; +} +.ui-button-icons-only { + width: 3.4em; +} +button.ui-button-icons-only { + width: 3.7em; +} + +/* button text element */ +.ui-button .ui-button-text { + display: block; + line-height: normal; +} +.ui-button-text-only .ui-button-text { + padding: .4em 1em; +} +.ui-button-icon-only .ui-button-text, +.ui-button-icons-only .ui-button-text { + padding: .4em; + text-indent: -9999999px; +} +.ui-button-text-icon-primary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 1em .4em 2.1em; +} +.ui-button-text-icon-secondary .ui-button-text, +.ui-button-text-icons .ui-button-text { + padding: .4em 2.1em .4em 1em; +} +.ui-button-text-icons .ui-button-text { + padding-left: 2.1em; + padding-right: 2.1em; +} +/* no icon support for input elements, provide padding by default */ +input.ui-button { + padding: .4em 1em; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon, +.ui-button-text-icon-primary .ui-icon, +.ui-button-text-icon-secondary .ui-icon, +.ui-button-text-icons .ui-icon, +.ui-button-icons-only .ui-icon { + position: absolute; + top: 50%; + margin-top: -8px; +} +.ui-button-icon-only .ui-icon { + left: 50%; + margin-left: -8px; +} +.ui-button-text-icon-primary .ui-button-icon-primary, +.ui-button-text-icons .ui-button-icon-primary, +.ui-button-icons-only .ui-button-icon-primary { + left: .5em; +} +.ui-button-text-icon-secondary .ui-button-icon-secondary, +.ui-button-text-icons .ui-button-icon-secondary, +.ui-button-icons-only .ui-button-icon-secondary { + right: .5em; +} + +/* button sets */ +.ui-buttonset { + margin-right: 7px; +} +.ui-buttonset .ui-button { + margin-left: 0; + margin-right: -.3em; +} + +/* workarounds */ +/* reset extra padding in Firefox, see h5bp.com/l */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month-year { + width: 100%; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 49%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 21px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-se { + width: 12px; + height: 12px; + right: -5px; + bottom: -5px; + background-position: 16px 16px; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-menu { + list-style: none; + padding: 2px; + margin: 0; + display: block; + outline: none; +} +.ui-menu .ui-menu { + margin-top: -3px; + position: absolute; +} +.ui-menu .ui-menu-item { + margin: 0; + padding: 0; + width: 100%; + /* support: IE10, see #8844 */ + list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); +} +.ui-menu .ui-menu-divider { + margin: 5px -2px 5px -2px; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-menu-item a { + text-decoration: none; + display: block; + padding: 2px .4em; + line-height: 1.5; + min-height: 0; /* support: IE7 */ + font-weight: normal; +} +.ui-menu .ui-menu-item a.ui-state-focus, +.ui-menu .ui-menu-item a.ui-state-active { + font-weight: normal; + margin: -1px; +} + +.ui-menu .ui-state-disabled { + font-weight: normal; + margin: .4em 0 .2em; + line-height: 1.5; +} +.ui-menu .ui-state-disabled a { + cursor: default; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item a { + position: relative; + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: .2em; + left: .2em; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + position: static; + float: right; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("images/animated-overlay.gif"); + height: 100%; + filter: alpha(opacity=25); + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: default; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* For IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 22px; +} +.ui-spinner-button { + width: 16px; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to overide default borders */ +.ui-spinner a.ui-spinner-button { + border-top: none; + border-bottom: none; + border-right: none; +} +/* vertical centre icon */ +.ui-spinner .ui-icon { + position: absolute; + margin-top: -8px; + top: 50%; + left: 0; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} + +/* TR overrides */ +.ui-spinner .ui-icon-triangle-1-s { + /* need to fix icons sprite */ + background-position: -65px -16px; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav li a { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active a, +.ui-tabs .ui-tabs-nav li.ui-state-disabled a, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading a { + cursor: text; +} +.ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; + -webkit-box-shadow: 0 0 5px #aaa; + box-shadow: 0 0 5px #aaa; +} +body .ui-tooltip { + border-width: 2px; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; + font-size: 1.1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Lucida Grande,Lucida Sans,Arial,sans-serif; + font-size: 1em; +} +.ui-widget-content { + border: 1px solid #a6c9e2; + background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; + color: #222222; +} +.ui-widget-content a { + color: #222222; +} +.ui-widget-header { + border: 1px solid #4297d7; + background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; + color: #ffffff; + font-weight: bold; +} +.ui-widget-header a { + color: #ffffff; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default { + border: 1px solid #c5dbec; + background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #2e6e9e; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited { + color: #2e6e9e; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus { + border: 1px solid #79b7e7; + background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; + font-weight: bold; + color: #1d5987; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited { + color: #1d5987; + text-decoration: none; +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active { + border: 1px solid #79b7e7; + background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; + font-weight: bold; + color: #e17009; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #e17009; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #fad42e; + background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; + color: #363636; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #363636; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #cd0a0a; + background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; + color: #cd0a0a; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #cd0a0a; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #cd0a0a; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + filter:Alpha(Opacity=70); + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + filter:Alpha(Opacity=35); + background-image: none; +} +.ui-state-disabled .ui-icon { + filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url(images/ui-icons_469bdd_256x240.png); +} +.ui-widget-header .ui-icon { + background-image: url(images/ui-icons_d8e7f3_256x240.png); +} +.ui-state-default .ui-icon { + background-image: url(images/ui-icons_6da8d5_256x240.png); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon { + background-image: url(images/ui-icons_217bc0_256x240.png); +} +.ui-state-active .ui-icon { + background-image: url(images/ui-icons_f9bd01_256x240.png); +} +.ui-state-highlight .ui-icon { + background-image: url(images/ui-icons_2e83ff_256x240.png); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url(images/ui-icons_cd0a0a_256x240.png); +} + +/* positioning */ +.ui-icon-blank { background-position: 16px 16px; } +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 5px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 5px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 5px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 5px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); +} +.ui-widget-shadow { + margin: -8px 0 0 -8px; + padding: 8px; + background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; + opacity: .3; + filter: Alpha(Opacity=30); + border-radius: 8px; +} diff --git a/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.min.css b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.min.css new file mode 100644 index 0000000000000000000000000000000000000000..b5329625293faf21c698ef83866918a4f5a3070e --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.10.3 - 2013-08-25 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande%2CLucida%20Sans%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=gloss_wave&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=inset_hard&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=glass&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=flat&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted #000}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:0}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:400}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:400;margin:-1px}.ui-menu .ui-state-disabled{font-weight:400;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url(images/animated-overlay.gif);height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Lucida Grande,Lucida Sans,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #a6c9e2;background:#fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #4297d7;background:#5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #c5dbec;background:#dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#2e6e9e}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#2e6e9e;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #79b7e7;background:#d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1d5987}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#1d5987;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #79b7e7;background:#f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x;font-weight:bold;color:#e17009}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#e17009;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fad42e;background:#fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_469bdd_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_d8e7f3_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_6da8d5_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_217bc0_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_f9bd01_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:5px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:5px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:5px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui-noscript.css b/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui-noscript.css new file mode 100644 index 0000000000000000000000000000000000000000..c4504855951d8490908cfb2a4e4c00cb29b802e0 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui-noscript.css @@ -0,0 +1,27 @@ +@charset "UTF-8"; +/* + * jQuery File Upload UI Plugin NoScript CSS 1.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2012, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +.fileinput-button input { + position: static; + opacity: 1; + filter: none; + transform: none; + font-size: inherit; + direction: inherit; +} + +.fileinput-button span, +.fileinput-button i, +.fileupload-buttonbar .delete, +.fileupload-buttonbar .toggle { + display: none; +} diff --git a/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui.css b/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui.css new file mode 100644 index 0000000000000000000000000000000000000000..f81b34c7b091b9ec956e53cd9ff2e05230537912 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/css/jquery.fileupload-ui.css @@ -0,0 +1,68 @@ +@charset "UTF-8"; +/* + * jQuery File Upload UI Plugin CSS 8.8.1 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +.fileinput-button { + position: relative; + overflow: hidden; +} +.fileinput-button input { + position: absolute; + top: 0; + right: 0; + margin: 0; + opacity: 0; + filter: alpha(opacity=0); + transform: translate(-300px, 0) scale(4); + font-size: 23px; + direction: ltr; + cursor: pointer; +} +.fileupload-buttonbar .btn, +.fileupload-buttonbar .toggle { + margin-bottom: 5px; +} +.progress-animated .progress-bar, +.progress-animated .bar { + background: url(../img/progressbar.gif) !important; + filter: none; +} +.fileupload-loading { + float: right; + width: 32px; + height: 32px; + background: url(../img/loading.gif) center no-repeat; + background-size: contain; + display: none; +} +.fileupload-processing .fileupload-loading { + display: block; +} +.files audio, +.files video { + max-width: 300px; +} + +@media (max-width: 767px) { + .fileupload-buttonbar .toggle, + .files .toggle, + .files .btn span { + display: none; + } + .files .name { + width: 80px; + word-wrap: break-word; + } + .files audio, + .files video { + max-width: 80px; + } +} diff --git a/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.js b/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.js new file mode 100644 index 0000000000000000000000000000000000000000..c3b58732a8882e7d10890d25aa25db339ee40c87 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.js @@ -0,0 +1,2006 @@ +/* + * 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/ + */ +/** +* bootstrap.js v3.0.0 by @fat and @mdo +* Copyright 2013 Twitter Inc. +* http://www.apache.org/licenses/LICENSE-2.0 +*/ +if (!jQuery) { throw new Error("Bootstrap requires jQuery") } + +/* ======================================================================== + * Bootstrap: transition.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#transitions + * ======================================================================== + * Copyright 2013 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ + + function transitionEnd() { + var el = document.createElement('bootstrap') + + var transEndEventNames = { + 'WebkitTransition' : 'webkitTransitionEnd' + , 'MozTransition' : 'transitionend' + , 'OTransition' : 'oTransitionEnd otransitionend' + , 'transition' : 'transitionend' + } + + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return { end: transEndEventNames[name] } + } + } + } + + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false, $el = this + $(this).one($.support.transition.end, function () { called = true }) + var callback = function () { if (!called) $($el).trigger($.support.transition.end) } + setTimeout(callback, duration) + return this + } + + $(function () { + $.support.transition = transitionEnd() + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: alert.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#alerts + * ======================================================================== + * Copyright 2013 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // ALERT CLASS DEFINITION + // ====================== + + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } + + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = $(selector) + + if (e) e.preventDefault() + + if (!$parent.length) { + $parent = $this.hasClass('alert') ? $this : $this.parent() + } + + $parent.trigger(e = $.Event('close.bs.alert')) + + if (e.isDefaultPrevented()) return + + $parent.removeClass('in') + + function removeElement() { + $parent.trigger('closed.bs.alert').remove() + } + + $.support.transition && $parent.hasClass('fade') ? + $parent + .one($.support.transition.end, removeElement) + .emulateTransitionEnd(150) : + removeElement() + } + + + // ALERT PLUGIN DEFINITION + // ======================= + + var old = $.fn.alert + + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') + + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.alert.Constructor = Alert + + + // ALERT NO CONFLICT + // ================= + + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } + + + // ALERT DATA-API + // ============== + + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: button.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#buttons + * ======================================================================== + * Copyright 2013 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + } + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state = state + 'Text' + + if (!data.resetText) $el.data('resetText', $el[val]()) + + $el[val](data[state] || this.options[state]) + + // push to event loop to allow forms to submit + setTimeout(function () { + state == 'loadingText' ? + $el.addClass(d).attr(d, d) : + $el.removeClass(d).removeAttr(d); + }, 0) + } + + Button.prototype.toggle = function () { + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + .prop('checked', !this.$element.hasClass('active')) + .trigger('change') + if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active') + } + + this.$element.toggleClass('active') + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + var old = $.fn.button + + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + e.preventDefault() + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: carousel.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#carousel + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = + this.sliding = + this.interval = + this.$active = + this.$items = null + + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } + + Carousel.DEFAULTS = { + interval: 5000 + , pause: 'hover' + , wrap: true + } + + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) + + this.interval && clearInterval(this.interval) + + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + + return this + } + + Carousel.prototype.getActiveIndex = function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() + + return this.$items.index(this.$active) + } + + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getActiveIndex() + + if (pos > (this.$items.length - 1) || pos < 0) return + + if (this.sliding) return this.$element.one('slid', function () { that.to(pos) }) + if (activeIndex == pos) return this.pause().cycle() + + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } + + Carousel.prototype.pause = function (e) { + e || (this.paused = true) + + if (this.$element.find('.next, .prev').length && $.support.transition.end) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } + + this.interval = clearInterval(this.interval) + + return this + } + + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } + + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } + + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } + + this.sliding = true + + isCycling && this.pause() + + var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) + + if ($next.hasClass('active')) return + + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } + + if ($.support.transition && this.$element.hasClass('slide')) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { that.$element.trigger('slid') }, 0) + }) + .emulateTransitionEnd(600) + } else { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid') + } + + isCycling && this.cycle() + + return this + } + + + // CAROUSEL PLUGIN DEFINITION + // ========================== + + var old = $.fn.carousel + + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide + + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } + + $.fn.carousel.Constructor = Carousel + + + // CAROUSEL NO CONFLICT + // ==================== + + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } + + + // CAROUSEL DATA-API + // ================= + + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false + + $target.carousel(options) + + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('bs.carousel').to(slideIndex) + } + + e.preventDefault() + }) + + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + $carousel.carousel($carousel.data()) + }) + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: collapse.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#collapse + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ + + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null + + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } + + Collapse.DEFAULTS = { + toggle: true + } + + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } + + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return + + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var actives = this.$parent && this.$parent.find('> .panel > .in') + + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('bs.collapse', null) + } + + var dimension = this.dimension() + + this.$element + .removeClass('collapse') + .addClass('collapsing') + [dimension](0) + + this.transitioning = 1 + + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('in') + [dimension]('auto') + this.transitioning = 0 + this.$element.trigger('shown.bs.collapse') + } + + if (!$.support.transition) return complete.call(this) + + var scrollSize = $.camelCase(['scroll', dimension].join('-')) + + this.$element + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + [dimension](this.$element[0][scrollSize]) + } + + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return + + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return + + var dimension = this.dimension() + + this.$element + [dimension](this.$element[dimension]()) + [0].offsetHeight + + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') + + this.transitioning = 1 + + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } + + if (!$.support.transition) return complete.call(this) + + this.$element + [dimension](0) + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + } + + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } + + + // COLLAPSE PLUGIN DEFINITION + // ========================== + + var old = $.fn.collapse + + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.collapse.Constructor = Collapse + + + // COLLAPSE NO CONFLICT + // ==================== + + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } + + + // COLLAPSE DATA-API + // ================= + + $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) + + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } + + $target.collapse(option) + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: dropdown.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#dropdowns + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + var $el = $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we we use a backdrop because click events don't delegate + $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) + } + + $parent.trigger(e = $.Event('show.bs.dropdown')) + + if (e.isDefaultPrevented()) return + + $parent + .toggleClass('open') + .trigger('shown.bs.dropdown') + + $this.focus() + } + + return false + } + + Dropdown.prototype.keydown = function (e) { + if (!/(38|40|27)/.test(e.keyCode)) return + + var $this = $(this) + + e.preventDefault() + e.stopPropagation() + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + if (!isActive || (isActive && e.keyCode == 27)) { + if (e.which == 27) $parent.find(toggle).focus() + return $this.click() + } + + var $items = $('[role=menu] li:not(.divider):visible a', $parent) + + if (!$items.length) return + + var index = $items.index($items.filter(':focus')) + + if (e.keyCode == 38 && index > 0) index-- // up + if (e.keyCode == 40 && index < $items.length - 1) index++ // down + if (!~index) index=0 + + $items.eq(index).focus() + } + + function clearMenus() { + $(backdrop).remove() + $(toggle).each(function (e) { + var $parent = getParent($(this)) + if (!$parent.hasClass('open')) return + $parent.trigger(e = $.Event('hide.bs.dropdown')) + if (e.isDefaultPrevented()) return + $parent.removeClass('open').trigger('hidden.bs.dropdown') + }) + } + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + var $parent = selector && $(selector) + + return $parent && $parent.length ? $parent : $this.parent() + } + + + // DROPDOWN PLUGIN DEFINITION + // ========================== + + var old = $.fn.dropdown + + $.fn.dropdown = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('dropdown') + + if (!data) $this.data('dropdown', (data = new Dropdown(this))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.dropdown.Constructor = Dropdown + + + // DROPDOWN NO CONFLICT + // ==================== + + $.fn.dropdown.noConflict = function () { + $.fn.dropdown = old + return this + } + + + // APPLY TO STANDARD DROPDOWN ELEMENTS + // =================================== + + $(document) + .on('click.bs.dropdown.data-api', clearMenus) + .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) + .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle) + .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: modal.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#modals + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // MODAL CLASS DEFINITION + // ====================== + + var Modal = function (element, options) { + this.options = options + this.$element = $(element) + this.$backdrop = + this.isShown = null + + if (this.options.remote) this.$element.load(this.options.remote) + } + + Modal.DEFAULTS = { + backdrop: true + , keyboard: true + , show: true + } + + Modal.prototype.toggle = function (_relatedTarget) { + return this[!this.isShown ? 'show' : 'hide'](_relatedTarget) + } + + Modal.prototype.show = function (_relatedTarget) { + var that = this + var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget }) + + this.$element.trigger(e) + + if (this.isShown || e.isDefaultPrevented()) return + + this.isShown = true + + this.escape() + + this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + + this.backdrop(function () { + var transition = $.support.transition && that.$element.hasClass('fade') + + if (!that.$element.parent().length) { + that.$element.appendTo(document.body) // don't move modals dom position + } + + that.$element.show() + + if (transition) { + that.$element[0].offsetWidth // force reflow + } + + that.$element + .addClass('in') + .attr('aria-hidden', false) + + that.enforceFocus() + + var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) + + transition ? + that.$element.find('.modal-dialog') // wait for modal to slide in + .one($.support.transition.end, function () { + that.$element.focus().trigger(e) + }) + .emulateTransitionEnd(300) : + that.$element.focus().trigger(e) + }) + } + + Modal.prototype.hide = function (e) { + if (e) e.preventDefault() + + e = $.Event('hide.bs.modal') + + this.$element.trigger(e) + + if (!this.isShown || e.isDefaultPrevented()) return + + this.isShown = false + + this.escape() + + $(document).off('focusin.bs.modal') + + this.$element + .removeClass('in') + .attr('aria-hidden', true) + .off('click.dismiss.modal') + + $.support.transition && this.$element.hasClass('fade') ? + this.$element + .one($.support.transition.end, $.proxy(this.hideModal, this)) + .emulateTransitionEnd(300) : + this.hideModal() + } + + Modal.prototype.enforceFocus = function () { + $(document) + .off('focusin.bs.modal') // guard against infinite focus loop + .on('focusin.bs.modal', $.proxy(function (e) { + if (this.$element[0] !== e.target && !this.$element.has(e.target).length) { + this.$element.focus() + } + }, this)) + } + + Modal.prototype.escape = function () { + if (this.isShown && this.options.keyboard) { + this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { + e.which == 27 && this.hide() + }, this)) + } else if (!this.isShown) { + this.$element.off('keyup.dismiss.bs.modal') + } + } + + Modal.prototype.hideModal = function () { + var that = this + this.$element.hide() + this.backdrop(function () { + that.removeBackdrop() + that.$element.trigger('hidden.bs.modal') + }) + } + + Modal.prototype.removeBackdrop = function () { + this.$backdrop && this.$backdrop.remove() + this.$backdrop = null + } + + Modal.prototype.backdrop = function (callback) { + var that = this + var animate = this.$element.hasClass('fade') ? 'fade' : '' + + if (this.isShown && this.options.backdrop) { + var doAnimate = $.support.transition && animate + + this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') + .appendTo(document.body) + + this.$element.on('click.dismiss.modal', $.proxy(function (e) { + if (e.target !== e.currentTarget) return + this.options.backdrop == 'static' + ? this.$element[0].focus.call(this.$element[0]) + : this.hide.call(this) + }, this)) + + if (doAnimate) this.$backdrop[0].offsetWidth // force reflow + + this.$backdrop.addClass('in') + + if (!callback) return + + doAnimate ? + this.$backdrop + .one($.support.transition.end, callback) + .emulateTransitionEnd(150) : + callback() + + } else if (!this.isShown && this.$backdrop) { + this.$backdrop.removeClass('in') + + $.support.transition && this.$element.hasClass('fade')? + this.$backdrop + .one($.support.transition.end, callback) + .emulateTransitionEnd(150) : + callback() + + } else if (callback) { + callback() + } + } + + + // MODAL PLUGIN DEFINITION + // ======================= + + var old = $.fn.modal + + $.fn.modal = function (option, _relatedTarget) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.modal') + var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('bs.modal', (data = new Modal(this, options))) + if (typeof option == 'string') data[option](_relatedTarget) + else if (options.show) data.show(_relatedTarget) + }) + } + + $.fn.modal.Constructor = Modal + + + // MODAL NO CONFLICT + // ================= + + $.fn.modal.noConflict = function () { + $.fn.modal = old + return this + } + + + // MODAL DATA-API + // ============== + + $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) { + var $this = $(this) + var href = $this.attr('href') + var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7 + var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data()) + + e.preventDefault() + + $target + .modal(option, this) + .one('hide', function () { + $this.is(':visible') && $this.focus() + }) + }) + + $(document) + .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') }) + .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: tooltip.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = + this.options = + this.enabled = + this.timeout = + this.hoverState = + this.$element = null + + this.init('tooltip', element, options) + } + + Tooltip.DEFAULTS = { + animation: true + , placement: 'top' + , selector: false + , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>' + , trigger: 'hover focus' + , title: '' + , delay: 0 + , html: false + , container: false + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay + , hide: options.delay + } + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.'+ this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + var $tip = this.tip() + + this.setContent() + + if (this.options.animation) $tip.addClass('fade') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var $parent = this.$element.parent() + + var orgPlacement = placement + var docScroll = document.documentElement.scrollTop || document.body.scrollTop + var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth() + var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight() + var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left + + placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' : + placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' : + placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' : + placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + this.$element.trigger('shown.bs.' + this.type) + } + } + + Tooltip.prototype.applyPlacement = function(offset, placement) { + var replace + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top = offset.top + marginTop + offset.left = offset.left + marginLeft + + $tip + .offset(offset) + .addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + replace = true + offset.top = offset.top + height - actualHeight + } + + if (/bottom|top/.test(placement)) { + var delta = 0 + + if (offset.left < 0) { + delta = offset.left * -2 + offset.left = 0 + + $tip.offset(offset) + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + } + + this.replaceArrow(delta - width + actualWidth, actualWidth, 'left') + } else { + this.replaceArrow(actualHeight - height, actualHeight, 'top') + } + + if (replace) $tip.offset(offset) + } + + Tooltip.prototype.replaceArrow = function(delta, dimension, position) { + this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title) + $tip.removeClass('fade in top bottom left right') + } + + Tooltip.prototype.hide = function () { + var that = this + var $tip = this.tip() + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') $tip.detach() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && this.$tip.hasClass('fade') ? + $tip + .one($.support.transition.end, complete) + .emulateTransitionEnd(150) : + complete() + + this.$element.trigger('hidden.bs.' + this.type) + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function () { + var el = this.$element[0] + return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : { + width: el.offsetWidth + , height: el.offsetHeight + }, this.$element.offset()) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.tip = function () { + return this.$tip = this.$tip || $(this.options.template) + } + + Tooltip.prototype.arrow = function () { + return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow') + } + + Tooltip.prototype.validate = function () { + if (!this.$element[0].parentNode) { + this.hide() + this.$element = null + this.options = null + } + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + + Tooltip.prototype.destroy = function () { + this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) + } + + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + var old = $.fn.tooltip + + $.fn.tooltip = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: popover.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#popovers + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') + + Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right' + , trigger: 'click' + , content: '' + , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>' + }) + + + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) + + Popover.prototype.constructor = Popover + + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } + + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + + $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content) + + $tip.removeClass('fade top bottom left right in') + + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide() + } + + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() + } + + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } + + Popover.prototype.arrow = function () { + return this.$arrow = this.$arrow || this.tip().find('.arrow') + } + + Popover.prototype.tip = function () { + if (!this.$tip) this.$tip = $(this.options.template) + return this.$tip + } + + + // POPOVER PLUGIN DEFINITION + // ========================= + + var old = $.fn.popover + + $.fn.popover = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.popover.Constructor = Popover + + + // POPOVER NO CONFLICT + // =================== + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: scrollspy.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#scrollspy + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // SCROLLSPY CLASS DEFINITION + // ========================== + + function ScrollSpy(element, options) { + var href + var process = $.proxy(this.process, this) + + this.$element = $(element).is('body') ? $(window) : $(element) + this.$body = $('body') + this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process) + this.options = $.extend({}, ScrollSpy.DEFAULTS, options) + this.selector = (this.options.target + || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + || '') + ' .nav li > a' + this.offsets = $([]) + this.targets = $([]) + this.activeTarget = null + + this.refresh() + this.process() + } + + ScrollSpy.DEFAULTS = { + offset: 10 + } + + ScrollSpy.prototype.refresh = function () { + var offsetMethod = this.$element[0] == window ? 'offset' : 'position' + + this.offsets = $([]) + this.targets = $([]) + + var self = this + var $targets = this.$body + .find(this.selector) + .map(function () { + var $el = $(this) + var href = $el.data('target') || $el.attr('href') + var $href = /^#\w/.test(href) && $(href) + + return ($href + && $href.length + && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null + }) + .sort(function (a, b) { return a[0] - b[0] }) + .each(function () { + self.offsets.push(this[0]) + self.targets.push(this[1]) + }) + } + + ScrollSpy.prototype.process = function () { + var scrollTop = this.$scrollElement.scrollTop() + this.options.offset + var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight + var maxScroll = scrollHeight - this.$scrollElement.height() + var offsets = this.offsets + var targets = this.targets + var activeTarget = this.activeTarget + var i + + if (scrollTop >= maxScroll) { + return activeTarget != (i = targets.last()[0]) && this.activate(i) + } + + for (i = offsets.length; i--;) { + activeTarget != targets[i] + && scrollTop >= offsets[i] + && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) + && this.activate( targets[i] ) + } + } + + ScrollSpy.prototype.activate = function (target) { + this.activeTarget = target + + $(this.selector) + .parents('.active') + .removeClass('active') + + var selector = this.selector + + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' + + var active = $(selector) + .parents('li') + .addClass('active') + + if (active.parent('.dropdown-menu').length) { + active = active + .closest('li.dropdown') + .addClass('active') + } + + active.trigger('activate') + } + + + // SCROLLSPY PLUGIN DEFINITION + // =========================== + + var old = $.fn.scrollspy + + $.fn.scrollspy = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.scrollspy') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.scrollspy.Constructor = ScrollSpy + + + // SCROLLSPY NO CONFLICT + // ===================== + + $.fn.scrollspy.noConflict = function () { + $.fn.scrollspy = old + return this + } + + + // SCROLLSPY DATA-API + // ================== + + $(window).on('load', function () { + $('[data-spy="scroll"]').each(function () { + var $spy = $(this) + $spy.scrollspy($spy.data()) + }) + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: tab.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#tabs + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // TAB CLASS DEFINITION + // ==================== + + var Tab = function (element) { + this.element = $(element) + } + + Tab.prototype.show = function () { + var $this = this.element + var $ul = $this.closest('ul:not(.dropdown-menu)') + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 + } + + if ($this.parent('li').hasClass('active')) return + + var previous = $ul.find('.active:last a')[0] + var e = $.Event('show.bs.tab', { + relatedTarget: previous + }) + + $this.trigger(e) + + if (e.isDefaultPrevented()) return + + var $target = $(selector) + + this.activate($this.parent('li'), $ul) + this.activate($target, $target.parent(), function () { + $this.trigger({ + type: 'shown.bs.tab' + , relatedTarget: previous + }) + }) + } + + Tab.prototype.activate = function (element, container, callback) { + var $active = container.find('> .active') + var transition = callback + && $.support.transition + && $active.hasClass('fade') + + function next() { + $active + .removeClass('active') + .find('> .dropdown-menu > .active') + .removeClass('active') + + element.addClass('active') + + if (transition) { + element[0].offsetWidth // reflow for transition + element.addClass('in') + } else { + element.removeClass('fade') + } + + if (element.parent('.dropdown-menu')) { + element.closest('li.dropdown').addClass('active') + } + + callback && callback() + } + + transition ? + $active + .one($.support.transition.end, next) + .emulateTransitionEnd(150) : + next() + + $active.removeClass('in') + } + + + // TAB PLUGIN DEFINITION + // ===================== + + var old = $.fn.tab + + $.fn.tab = function ( option ) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tab') + + if (!data) $this.data('bs.tab', (data = new Tab(this))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.tab.Constructor = Tab + + + // TAB NO CONFLICT + // =============== + + $.fn.tab.noConflict = function () { + $.fn.tab = old + return this + } + + + // TAB DATA-API + // ============ + + $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { + e.preventDefault() + $(this).tab('show') + }) + +}(window.jQuery); + +/* ======================================================================== + * Bootstrap: affix.js v3.0.0 + * http://twbs.github.com/bootstrap/javascript.html#affix + * ======================================================================== + * Copyright 2012 Twitter, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ======================================================================== */ + + ++function ($) { "use strict"; + + // AFFIX CLASS DEFINITION + // ====================== + + var Affix = function (element, options) { + this.options = $.extend({}, Affix.DEFAULTS, options) + this.$window = $(window) + .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this)) + .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) + + this.$element = $(element) + this.affixed = + this.unpin = null + + this.checkPosition() + } + + Affix.RESET = 'affix affix-top affix-bottom' + + Affix.DEFAULTS = { + offset: 0 + } + + Affix.prototype.checkPositionWithEventLoop = function () { + setTimeout($.proxy(this.checkPosition, this), 1) + } + + Affix.prototype.checkPosition = function () { + if (!this.$element.is(':visible')) return + + var scrollHeight = $(document).height() + var scrollTop = this.$window.scrollTop() + var position = this.$element.offset() + var offset = this.options.offset + var offsetTop = offset.top + var offsetBottom = offset.bottom + + if (typeof offset != 'object') offsetBottom = offsetTop = offset + if (typeof offsetTop == 'function') offsetTop = offset.top() + if (typeof offsetBottom == 'function') offsetBottom = offset.bottom() + + var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false : + offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' : + offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false + + if (this.affixed === affix) return + if (this.unpin) this.$element.css('top', '') + + this.affixed = affix + this.unpin = affix == 'bottom' ? position.top - scrollTop : null + + this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : '')) + + if (affix == 'bottom') { + this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() }) + } + } + + + // AFFIX PLUGIN DEFINITION + // ======================= + + var old = $.fn.affix + + $.fn.affix = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.affix') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.affix', (data = new Affix(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + $.fn.affix.Constructor = Affix + + + // AFFIX NO CONFLICT + // ================= + + $.fn.affix.noConflict = function () { + $.fn.affix = old + return this + } + + + // AFFIX DATA-API + // ============== + + $(window).on('load', function () { + $('[data-spy="affix"]').each(function () { + var $spy = $(this) + var data = $spy.data() + + data.offset = data.offset || {} + + if (data.offsetBottom) data.offset.bottom = data.offsetBottom + if (data.offsetTop) data.offset.top = data.offsetTop + + $spy.affix(data) + }) + }) + +}(window.jQuery); diff --git a/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.min.js b/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.min.js new file mode 100644 index 0000000000000000000000000000000000000000..b897fe93ac3e3b3aa7263ef60416d4edab7f9fb4 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/bootstrap/bootstrap.min.js @@ -0,0 +1,13 @@ +/* + * 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/ + */ +/** +* bootstrap.js v3.0.0 by @fat and @mdo +* Copyright 2013 Twitter Inc. +* http://www.apache.org/licenses/LICENSE-2.0 +*/ +if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('<div class="dropdown-backdrop"/>').insertAfter(a(this)).on("click",b),f.trigger(d=a.Event("show.bs.dropdown")),d.isDefaultPrevented())return;f.toggleClass("open").trigger("shown.bs.dropdown"),e.focus()}return!1}},f.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var f=c(d),g=f.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&f.find(e).focus(),d.click();var h=a("[role=menu] li:not(.divider):visible a",f);if(h.length){var i=h.index(h.filter(":focus"));38==b.keyCode&&i>0&&i--,40==b.keyCode&&i<h.length-1&&i++,~i||(i=0),h.eq(i).focus()}}}};var g=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var c=a(this),d=c.data("dropdown");d||c.data("dropdown",d=new f(this)),"string"==typeof b&&d[b].call(c)})},a.fn.dropdown.Constructor=f,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=g,this},a(document).on("click.bs.dropdown.data-api",b).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",e,f.prototype.toggle).on("keydown.bs.dropdown.data-api",e+", [role=menu]",f.prototype.keydown)}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.options=c,this.$element=a(b),this.$backdrop=this.isShown=null,this.options.remote&&this.$element.load(this.options.remote)};b.DEFAULTS={backdrop:!0,keyboard:!0,show:!0},b.prototype.toggle=function(a){return this[this.isShown?"hide":"show"](a)},b.prototype.show=function(b){var c=this,d=a.Event("show.bs.modal",{relatedTarget:b});this.$element.trigger(d),this.isShown||d.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.$element.on("click.dismiss.modal",'[data-dismiss="modal"]',a.proxy(this.hide,this)),this.backdrop(function(){var d=a.support.transition&&c.$element.hasClass("fade");c.$element.parent().length||c.$element.appendTo(document.body),c.$element.show(),d&&c.$element[0].offsetWidth,c.$element.addClass("in").attr("aria-hidden",!1),c.enforceFocus();var e=a.Event("shown.bs.modal",{relatedTarget:b});d?c.$element.find(".modal-dialog").one(a.support.transition.end,function(){c.$element.focus().trigger(e)}).emulateTransitionEnd(300):c.$element.focus().trigger(e)}))},b.prototype.hide=function(b){b&&b.preventDefault(),b=a.Event("hide.bs.modal"),this.$element.trigger(b),this.isShown&&!b.isDefaultPrevented()&&(this.isShown=!1,this.escape(),a(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.modal"),a.support.transition&&this.$element.hasClass("fade")?this.$element.one(a.support.transition.end,a.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())},b.prototype.enforceFocus=function(){a(document).off("focusin.bs.modal").on("focusin.bs.modal",a.proxy(function(a){this.$element[0]===a.target||this.$element.has(a.target).length||this.$element.focus()},this))},b.prototype.escape=function(){this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.bs.modal",a.proxy(function(a){27==a.which&&this.hide()},this)):this.isShown||this.$element.off("keyup.dismiss.bs.modal")},b.prototype.hideModal=function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden.bs.modal")})},b.prototype.removeBackdrop=function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},b.prototype.backdrop=function(b){var c=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var d=a.support.transition&&c;if(this.$backdrop=a('<div class="modal-backdrop '+c+'" />').appendTo(document.body),this.$element.on("click.dismiss.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),d&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;d?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b).emulateTransitionEnd(150):b()):b&&b()};var c=a.fn.modal;a.fn.modal=function(c,d){return this.each(function(){var e=a(this),f=e.data("bs.modal"),g=a.extend({},b.DEFAULTS,e.data(),"object"==typeof c&&c);f||e.data("bs.modal",f=new b(this,g)),"string"==typeof c?f[c](d):g.show&&f.show(d)})},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f,this).one("hide",function(){c.is(":visible")&&c.focus()})}),a(document).on("show.bs.modal",".modal",function(){a(document.body).addClass("modal-open")}).on("hidden.bs.modal",".modal",function(){a(document.body).removeClass("modal-open")})}(window.jQuery),+function(a){"use strict";var b=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};b.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},b.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focus",i="hover"==g?"mouseleave":"blur";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},b.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},b.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show),void 0):c.show()},b.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type);return clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide),void 0):c.hide()},b.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){if(this.$element.trigger(b),b.isDefaultPrevented())return;var c=this.tip();this.setContent(),this.options.animation&&c.addClass("fade");var d="function"==typeof this.options.placement?this.options.placement.call(this,c[0],this.$element[0]):this.options.placement,e=/\s?auto?\s?/i,f=e.test(d);f&&(d=d.replace(e,"")||"top"),c.detach().css({top:0,left:0,display:"block"}).addClass(d),this.options.container?c.appendTo(this.options.container):c.insertAfter(this.$element);var g=this.getPosition(),h=c[0].offsetWidth,i=c[0].offsetHeight;if(f){var j=this.$element.parent(),k=d,l=document.documentElement.scrollTop||document.body.scrollTop,m="body"==this.options.container?window.innerWidth:j.outerWidth(),n="body"==this.options.container?window.innerHeight:j.outerHeight(),o="body"==this.options.container?0:j.offset().left;d="bottom"==d&&g.top+g.height+i-l>n?"top":"top"==d&&g.top-l-i<0?"bottom":"right"==d&&g.right+h>m?"left":"left"==d&&g.left-h<o?"right":d,c.removeClass(k).addClass(d)}var p=this.getCalculatedOffset(d,g,h,i);this.applyPlacement(p,d),this.$element.trigger("shown.bs."+this.type)}},b.prototype.applyPlacement=function(a,b){var c,d=this.tip(),e=d[0].offsetWidth,f=d[0].offsetHeight,g=parseInt(d.css("margin-top"),10),h=parseInt(d.css("margin-left"),10);isNaN(g)&&(g=0),isNaN(h)&&(h=0),a.top=a.top+g,a.left=a.left+h,d.offset(a).addClass("in");var i=d[0].offsetWidth,j=d[0].offsetHeight;if("top"==b&&j!=f&&(c=!0,a.top=a.top+f-j),/bottom|top/.test(b)){var k=0;a.left<0&&(k=-2*a.left,a.left=0,d.offset(a),i=d[0].offsetWidth,j=d[0].offsetHeight),this.replaceArrow(k-e+i,i,"left")}else this.replaceArrow(j-f,j,"top");c&&d.offset(a)},b.prototype.replaceArrow=function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},b.prototype.hide=function(){function b(){"in"!=c.hoverState&&d.detach()}var c=this,d=this.tip(),e=a.Event("hide.bs."+this.type);return this.$element.trigger(e),e.isDefaultPrevented()?void 0:(d.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?d.one(a.support.transition.end,b).emulateTransitionEnd(150):b(),this.$element.trigger("hidden.bs."+this.type),this)},b.prototype.fixTitle=function(){var a=this.$element;(a.attr("title")||"string"!=typeof a.attr("data-original-title"))&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},b.prototype.hasContent=function(){return this.getTitle()},b.prototype.getPosition=function(){var b=this.$element[0];return a.extend({},"function"==typeof b.getBoundingClientRect?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},b.prototype.getCalculatedOffset=function(a,b,c,d){return"bottom"==a?{top:b.top+b.height,left:b.left+b.width/2-c/2}:"top"==a?{top:b.top-d,left:b.left+b.width/2-c/2}:"left"==a?{top:b.top+b.height/2-d/2,left:b.left-c}:{top:b.top+b.height/2-d/2,left:b.left+b.width}},b.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},b.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},b.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},b.prototype.enable=function(){this.enabled=!0},b.prototype.disable=function(){this.enabled=!1},b.prototype.toggleEnabled=function(){this.enabled=!this.enabled},b.prototype.toggle=function(b){var c=b?a(b.currentTarget)[this.type](this.getDelegateOptions()).data("bs."+this.type):this;c.tip().hasClass("in")?c.leave(c):c.enter(c)},b.prototype.destroy=function(){this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof c&&c;e||d.data("bs.tooltip",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery),+function(a){"use strict";var b=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");b.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/js/holder.js b/dspace-jspui/src/main/webapp/static/js/holder.js new file mode 100644 index 0000000000000000000000000000000000000000..f564c0518df4cafc9e969ae1e977d6ebb0a9ee94 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/holder.js @@ -0,0 +1,426 @@ +/* + * 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/ + */ +/* + +Holder - 2.0 - client side image placeholders +(c) 2012-2013 Ivan Malopinsky / http://imsky.co + +Provided under the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 +Commercial use requires attribution. + +*/ + +var Holder = Holder || {}; +(function (app, win) { + +var preempted = false, +fallback = false, +canvas = document.createElement('canvas'); + +//getElementsByClassName polyfill +document.getElementsByClassName||(document.getElementsByClassName=function(e){var t=document,n,r,i,s=[];if(t.querySelectorAll)return t.querySelectorAll("."+e);if(t.evaluate){r=".//*[contains(concat(' ', @class, ' '), ' "+e+" ')]",n=t.evaluate(r,t,null,0,null);while(i=n.iterateNext())s.push(i)}else{n=t.getElementsByTagName("*"),r=new RegExp("(^|\\s)"+e+"(\\s|$)");for(i=0;i<n.length;i++)r.test(n[i].className)&&s.push(n[i])}return s}) + +//getComputedStyle polyfill +window.getComputedStyle||(window.getComputedStyle=function(e,t){return this.el=e,this.getPropertyValue=function(t){var n=/(\-([a-z]){1})/g;return t=="float"&&(t="styleFloat"),n.test(t)&&(t=t.replace(n,function(){return arguments[2].toUpperCase()})),e.currentStyle[t]?e.currentStyle[t]:null},this}) + +//http://javascript.nwbox.com/ContentLoaded by Diego Perini with modifications +function contentLoaded(n,t){var l="complete",s="readystatechange",u=!1,h=u,c=!0,i=n.document,a=i.documentElement,e=i.addEventListener?"addEventListener":"attachEvent",v=i.addEventListener?"removeEventListener":"detachEvent",f=i.addEventListener?"":"on",r=function(e){(e.type!=s||i.readyState==l)&&((e.type=="load"?n:i)[v](f+e.type,r,u),!h&&(h=!0)&&t.call(n,null))},o=function(){try{a.doScroll("left")}catch(n){setTimeout(o,50);return}r("poll")};if(i.readyState==l)t.call(n,"lazy");else{if(i.createEventObject&&a.doScroll){try{c=!n.frameElement}catch(y){}c&&o()}i[e](f+"DOMContentLoaded",r,u),i[e](f+s,r,u),n[e](f+"load",r,u)}}; + +//https://gist.github.com/991057 by Jed Schmidt with modifications +function selector(a){ + a=a.match(/^(\W)?(.*)/);var b=document["getElement"+(a[1]?a[1]=="#"?"ById":"sByClassName":"sByTagName")](a[2]); + var ret=[]; b!=null&&(b.length?ret=b:b.length==0?ret=b:ret=[b]); return ret; +} + +//shallow object property extend +function extend(a,b){var c={};for(var d in a)c[d]=a[d];for(var e in b)c[e]=b[e];return c} + +//hasOwnProperty polyfill +if (!Object.prototype.hasOwnProperty) + Object.prototype.hasOwnProperty = function(prop) { + var proto = this.__proto__ || this.constructor.prototype; + return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]); + } + +function text_size(width, height, template) { + height = parseInt(height,10); + width = parseInt(width,10); + var bigSide = Math.max(height, width) + var smallSide = Math.min(height, width) + var scale = 1 / 12; + var newHeight = Math.min(smallSide * 0.75, 0.75 * bigSide * scale); + return { + height: Math.round(Math.max(template.size, newHeight)) + } +} + +function draw(ctx, dimensions, template, ratio) { + var ts = text_size(dimensions.width, dimensions.height, template); + var text_height = ts.height; + var width = dimensions.width * ratio, + height = dimensions.height * ratio; + var font = template.font ? template.font : "sans-serif"; + canvas.width = width; + canvas.height = height; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + ctx.fillStyle = template.background; + ctx.fillRect(0, 0, width, height); + ctx.fillStyle = template.foreground; + ctx.font = "bold " + text_height + "px " + font; + var text = template.text ? template.text : (Math.floor(dimensions.width) + "x" + Math.floor(dimensions.height)); + var text_width = ctx.measureText(text).width; + if (text_width / width >= 0.75) { + text_height = Math.floor(text_height * 0.75 * (width/text_width)); + } + //Resetting font size if necessary + ctx.font = "bold " + (text_height * ratio) + "px " + font; + ctx.fillText(text, (width / 2), (height / 2), width); + return canvas.toDataURL("image/png"); +} + +function render(mode, el, holder, src) { + var dimensions = holder.dimensions, + theme = holder.theme, + text = holder.text ? decodeURIComponent(holder.text) : holder.text; + var dimensions_caption = dimensions.width + "x" + dimensions.height; + theme = (text ? extend(theme, { + text: text + }) : theme); + theme = (holder.font ? extend(theme, { + font: holder.font + }) : theme); + if (mode == "image") { + el.setAttribute("data-src", src); + el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (fallback || !holder.auto) { + el.style.width = dimensions.width + "px"; + el.style.height = dimensions.height + "px"; + } + if (fallback) { + el.style.backgroundColor = theme.background; + } else { + el.setAttribute("src", draw(ctx, dimensions, theme, ratio)); + } + } else if (mode == "background") { + if (!fallback) { + el.style.backgroundImage = "url(" + draw(ctx, dimensions, theme, ratio) + ")"; + el.style.backgroundSize = dimensions.width + "px " + dimensions.height + "px"; + } + } else if (mode == "fluid") { + el.setAttribute("data-src", src); + el.setAttribute("alt", text ? text : theme.text ? theme.text + " [" + dimensions_caption + "]" : dimensions_caption); + if (dimensions.height.substr(-1) == "%") { + el.style.height = dimensions.height + } else { + el.style.height = dimensions.height + "px" + } + if (dimensions.width.substr(-1) == "%") { + el.style.width = dimensions.width + } else { + el.style.width = dimensions.width + "px" + } + if (el.style.display == "inline" || el.style.display == "") { + el.style.display = "block"; + } + if (fallback) { + el.style.backgroundColor = theme.background; + } else { + el.holderData = holder; + fluid_images.push(el); + fluid_update(el); + } + } +}; + +function fluid_update(element) { + var images; + if (element.nodeType == null) { + images = fluid_images; + } else { + images = [element] + } + for (i in images) { + var el = images[i] + if (el.holderData) { + var holder = el.holderData; + el.setAttribute("src", draw(ctx, { + height: el.clientHeight, + width: el.clientWidth + }, holder.theme, ratio)); + } + } +} + +function parse_flags(flags, options) { + + var ret = { + theme: settings.themes.gray + }, render = false; + + for (sl = flags.length, j = 0; j < sl; j++) { + var flag = flags[j]; + if (app.flags.dimensions.match(flag)) { + render = true; + ret.dimensions = app.flags.dimensions.output(flag); + } else if (app.flags.fluid.match(flag)) { + render = true; + ret.dimensions = app.flags.fluid.output(flag); + ret.fluid = true; + } else if (app.flags.colors.match(flag)) { + ret.theme = app.flags.colors.output(flag); + } else if (options.themes[flag]) { + //If a theme is specified, it will override custom colors + ret.theme = options.themes[flag]; + } else if (app.flags.text.match(flag)) { + ret.text = app.flags.text.output(flag); + } else if (app.flags.font.match(flag)) { + ret.font = app.flags.font.output(flag); + } else if (app.flags.auto.match(flag)) { + ret.auto = true; + } + } + + return render ? ret : false; + +}; + + + +if (!canvas.getContext) { + fallback = true; +} else { + if (canvas.toDataURL("image/png") + .indexOf("data:image/png") < 0) { + //Android doesn't support data URI + fallback = true; + } else { + var ctx = canvas.getContext("2d"); + } +} + +var dpr = 1, bsr = 1; + +if(!fallback){ + dpr = window.devicePixelRatio || 1, + bsr = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1; +} + +var ratio = dpr / bsr; + +var fluid_images = []; + +var settings = { + domain: "holder.js", + images: "img", + bgnodes: ".holderjs", + themes: { + "gray": { + background: "#eee", + foreground: "#aaa", + size: 12 + }, + "social": { + background: "#3a5a97", + foreground: "#fff", + size: 12 + }, + "industrial": { + background: "#434A52", + foreground: "#C2F200", + size: 12 + } + }, + stylesheet: ".holderjs-fluid {font-size:16px;font-weight:bold;text-align:center;font-family:sans-serif;margin:0}" +}; + + +app.flags = { + dimensions: { + regex: /^(\d+)x(\d+)$/, + output: function (val) { + var exec = this.regex.exec(val); + return { + width: +exec[1], + height: +exec[2] + } + } + }, + fluid: { + regex: /^([0-9%]+)x([0-9%]+)$/, + output: function (val) { + var exec = this.regex.exec(val); + return { + width: exec[1], + height: exec[2] + } + } + }, + colors: { + regex: /#([0-9a-f]{3,})\:#([0-9a-f]{3,})/i, + output: function (val) { + var exec = this.regex.exec(val); + return { + size: settings.themes.gray.size, + foreground: "#" + exec[2], + background: "#" + exec[1] + } + } + }, + text: { + regex: /text\:(.*)/, + output: function (val) { + return this.regex.exec(val)[1]; + } + }, + font: { + regex: /font\:(.*)/, + output: function (val) { + return this.regex.exec(val)[1]; + } + }, + auto: { + regex: /^auto$/ + } +} + +for (var flag in app.flags) { + if (!app.flags.hasOwnProperty(flag)) continue; + app.flags[flag].match = function (val) { + return val.match(this.regex) + } +} + +app.add_theme = function (name, theme) { + name != null && theme != null && (settings.themes[name] = theme); + return app; +}; + +app.add_image = function (src, el) { + var node = selector(el); + if (node.length) { + for (var i = 0, l = node.length; i < l; i++) { + var img = document.createElement("img") + img.setAttribute("data-src", src); + node[i].appendChild(img); + } + } + return app; +}; + +app.run = function (o) { + var options = extend(settings, o), + images = [], imageNodes = [], bgnodes = []; + + if(typeof(options.images) == "string"){ + imageNodes = selector(options.images); + } + else if (window.NodeList && options.images instanceof window.NodeList) { + imageNodes = options.images; + } else if (window.Node && options.images instanceof window.Node) { + imageNodes = [options.images]; + } + + if(typeof(options.bgnodes) == "string"){ + bgnodes = selector(options.bgnodes); + } else if (window.NodeList && options.elements instanceof window.NodeList) { + bgnodes = options.bgnodes; + } else if (window.Node && options.bgnodes instanceof window.Node) { + bgnodes = [options.bgnodes]; + } + + preempted = true; + + for (i = 0, l = imageNodes.length; i < l; i++) images.push(imageNodes[i]); + + var holdercss = document.getElementById("holderjs-style"); + if (!holdercss) { + holdercss = document.createElement("style"); + holdercss.setAttribute("id", "holderjs-style"); + holdercss.type = "text/css"; + document.getElementsByTagName("head")[0].appendChild(holdercss); + } + + if (!options.nocss) { + if (holdercss.styleSheet) { + holdercss.styleSheet.cssText += options.stylesheet; + } else { + holdercss.appendChild(document.createTextNode(options.stylesheet)); + } + } + + var cssregex = new RegExp(options.domain + "\/(.*?)\"?\\)"); + + for (var l = bgnodes.length, i = 0; i < l; i++) { + var src = window.getComputedStyle(bgnodes[i], null) + .getPropertyValue("background-image"); + var flags = src.match(cssregex); + var bgsrc = bgnodes[i].getAttribute("data-background-src"); + + if (flags) { + var holder = parse_flags(flags[1].split("/"), options); + if (holder) { + render("background", bgnodes[i], holder, src); + } + } + else if(bgsrc != null){ + var holder = parse_flags(bgsrc.substr(bgsrc.lastIndexOf(options.domain) + options.domain.length + 1) + .split("/"), options); + if(holder){ + render("background", bgnodes[i], holder, src); + } + } + } + + for (l = images.length, i = 0; i < l; i++) { + + var attr_src = attr_data_src = src = null; + + try{ + attr_src = images[i].getAttribute("src"); + attr_datasrc = images[i].getAttribute("data-src"); + }catch(e){} + + if (attr_datasrc == null && !! attr_src && attr_src.indexOf(options.domain) >= 0) { + src = attr_src; + } else if ( !! attr_datasrc && attr_datasrc.indexOf(options.domain) >= 0) { + src = attr_datasrc; + } + + if (src) { + var holder = parse_flags(src.substr(src.lastIndexOf(options.domain) + options.domain.length + 1) + .split("/"), options); + if (holder) { + if (holder.fluid) { + render("fluid", images[i], holder, src) + } else { + render("image", images[i], holder, src); + } + } + } + } + return app; +}; + +contentLoaded(win, function () { + if (window.addEventListener) { + window.addEventListener("resize", fluid_update, false); + window.addEventListener("orientationchange", fluid_update, false); + } else { + window.attachEvent("onresize", fluid_update) + } + preempted || app.run(); +}); + +if (typeof define === "function" && define.amd) { + define("Holder", [], function () { + return app; + }); +} + +})(Holder, window); diff --git a/dspace-jspui/src/main/webapp/static/js/html5shiv.js b/dspace-jspui/src/main/webapp/static/js/html5shiv.js new file mode 100644 index 0000000000000000000000000000000000000000..9039884b420ab14a6fcfec76ab870e338adeddcf --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/html5shiv.js @@ -0,0 +1,15 @@ +/* + * 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/ + */ +/* + HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed +*/ +(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag(); +a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>"; +c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode|| +"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",version:"3.6.2pre",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment(); +for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document); diff --git a/dspace-jspui/src/main/webapp/static/js/jquery/jquery-1.10.2.min.js b/dspace-jspui/src/main/webapp/static/js/jquery/jquery-1.10.2.min.js new file mode 100644 index 0000000000000000000000000000000000000000..da4170647dd102aa92a57cb4936ff6dfa58d78c2 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/jquery/jquery-1.10.2.min.js @@ -0,0 +1,6 @@ +/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license +//@ sourceMappingURL=jquery-1.10.2.min.map +*/ +(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav></:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="<table><tr><td></td><td>t</td></tr></table>",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="<div></div>",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t +}({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/<tbody/i,wt=/<|&#?\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\s*(?:[^=]|=\s*.checked.)/i,kt=/^$|\/(?:java|ecma)script/i,Et=/^true\/(.*)/,St=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,At={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:x.support.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1></$2>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1></$2>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?"<table>"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); +u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,"display"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?"alpha(opacity="+100*t+")":"",o=r&&r.filter||n.filter||"";n.zoom=1,(t>=1||""===t)&&""===x.trim(o.replace($t,""))&&n.removeAttribute&&(n.removeAttribute("filter"),""===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+" "+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:"inline-block"},Wt,[e,"marginRight"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+"px":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&"none"===(e.style&&e.style.display||x.css(e,"display"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\[\]$/,fn=/\r?\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,"\r\n")}}):{name:t.name,value:n.replace(fn,"\r\n")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join("&").replace(cn,"+")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)gn(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var mn,yn,vn=x.now(),bn=/\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\/\//,En=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn="*/".concat("*");try{yn=o.href}catch(Ln){yn=a.createElement("a"),yn.href="",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return"string"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o["*"]&&s("*")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if("string"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(" ");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&"object"==typeof n&&(a="POST"),s.length>0&&x.ajax({url:e,type:a,dataType:"html",data:n}).done(function(e){o=arguments,s.html(i?x("<div>").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks("once memory"),m=p.statusCode||{},y={},v={},b=0,w="canceled",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||"*").toLowerCase().match(T)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?"80":"443"))===(mn[3]||("http:"===mn[1]?"80":"443")))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader("If-Modified-Since",x.lastModified[o]),x.etag[o]&&C.setRequestHeader("If-None-Match",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader("Content-Type",p.contentType),C.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w="abort";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger("ajaxSend",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort("timeout")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||"",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader("Last-Modified"),T&&(x.lastModified[o]=T),T=C.getResponseHeader("etag"),T&&(x.etag[o]=T)),204===e||"HEAD"===p.type?N="nocontent":304===e?N="notmodified":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N="error",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+"",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?"ajaxSuccess":"ajaxError",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger("ajaxComplete",[C,p]),--x.active||x.event.trigger("ajaxStop")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,n){return x.get(e,t,n,"script")}}),x.each(["get","post"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+" "+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if("*"===o)o=l;else if("*"!==l&&l!==o){if(a=u[l+" "+o]||u["* "+o],!a)for(i in u)if(s=i.split(" "),s[1]===o&&(a=u[l+" "+s[0]]||u["* "+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(p){return{state:"parsererror",error:a?p:"No conversion from "+l+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),x.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=a.head||x("head")[0]||a.documentElement;return{send:function(t,i){n=a.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Fn.pop()||x.expando+"_"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return l||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||x.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&"withCredentials"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),"string"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+w+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),a=(x.cssNumber[e]||"px"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||".5",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn["*"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&"expand"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,"fxshow");n.queue||(s=x._queueHooks(e,"fx"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,"fx").length||s.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(x.support.inlineBlockNeedsLayout&&"inline"!==ln(e.nodeName)?p.zoom=1:p.display="inline-block")),n.overflow&&(p.overflow="hidden",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?"hidden"in d&&(f=d.hidden):d=x._data(e,"fxshow",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=x._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,"position");"static"===r&&(e.style.position="relative");var i=x(e),o=i.offset(),a=x.css(e,"top"),s=x.css(e,"left"),l=("absolute"===r||"fixed"===r)&&x.inArray("auto",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),"using"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===x.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(n=e.offset()),n.top+=x.css(e[0],"borderTopWidth",!0),n.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-x.css(r,"marginTop",!0),left:t.left-n.left-x.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:"height",Width:"width"},function(e,n){x.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}))})(window); diff --git a/dspace-jspui/src/main/webapp/static/js/jquery/jquery-ui-1.10.3.custom.min.js b/dspace-jspui/src/main/webapp/static/js/jquery/jquery-ui-1.10.3.custom.min.js new file mode 100644 index 0000000000000000000000000000000000000000..b0def54ddbc48629beef6770e2dc2ed513897e1b --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/jquery/jquery-ui-1.10.3.custom.min.js @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.10.3 - 2013-08-25 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,m,g,v,b,_=t(e.of),y=t.position.getWithinInfo(e.within),w=t.position.getScrollInfo(y),x=(e.collision||"flip").split(" "),k={};return b=n(_),_[0].preventDefault&&(e.at="left top"),p=b.width,m=b.height,g=b.offset,v=t.extend({},g),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=l.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=l.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),k[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=m:"center"===e.at[1]&&(v.top+=m/2),a=i(k.at,p,m),v.left+=a[0],v.top+=a[1],this.each(function(){var n,l,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),b=s(this,"marginTop"),D=u+f+s(this,"marginRight")+w.width,T=d+b+s(this,"marginBottom")+w.height,C=t.extend({},v),M=i(k.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?C.left-=u:"center"===e.my[0]&&(C.left-=u/2),"bottom"===e.my[1]?C.top-=d:"center"===e.my[1]&&(C.top-=d/2),C.left+=M[0],C.top+=M[1],t.support.offsetFractions||(C.left=h(C.left),C.top=h(C.top)),n={marginLeft:f,marginTop:b},t.each(["left","top"],function(i,s){t.ui.position[x[i]]&&t.ui.position[x[i]][s](C,{targetWidth:p,targetHeight:m,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:D,collisionHeight:T,offset:[a[0]+M[0],a[1]+M[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(l=function(t){var i=g.left-C.left,s=i+p-u,n=g.top-C.top,a=n+m-d,h={target:{element:_,left:g.left,top:g.top,width:p,height:m},element:{element:c,left:C.left,top:C.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>m&&m>r(n+a)&&(h.vertical="middle"),h.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,h)}),c.offset(t.extend(C,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-o-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-o-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-o-a,t.top+p+f+m>c&&(0>s||r(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,t.top+p+f+m>u&&(i>0||u>r(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(e){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var i=this.options;return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||e.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1):!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,e(document).width()-this.helperProportions.width-this.margins.left,(e(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(t){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=t.pageX,l=t.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s]),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i){var s=e(this).data("ui-draggable"),n=s.options,a=e.extend({},i,{item:s.element});s.sortables=[],e(n.connectToSortable).each(function(){var i=e.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i){var s=e(this).data("ui-draggable"),n=e.extend({},i,{item:s.element});e.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,n))})},drag:function(t,i){var s=e(this).data("ui-draggable"),n=this;e.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",t),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",t),s.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),i=e(this).data("ui-draggable").options;t.css("cursor")&&(i._cursor=t.css("cursor")),t.css("cursor",i.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._opacity&&e(i.helper).css("opacity",s._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&"HTML"!==t.scrollParent[0].tagName&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var i=e(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:t.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-t.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:t.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(t.pageY-e(document).scrollTop()<s.scrollSensitivity?n=e(document).scrollTop(e(document).scrollTop()-s.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<s.scrollSensitivity&&(n=e(document).scrollTop(e(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(t.pageX-e(document).scrollLeft()<s.scrollSensitivity?n=e(document).scrollLeft(e(document).scrollLeft()-s.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<s.scrollSensitivity&&(n=e(document).scrollLeft(e(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(i,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),i=t.options;t.snapElements=[],e(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=e(this),s=i.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(t,i){var s,n,a,o,r,h,l,u,c,d,p=e(this).data("ui-draggable"),f=p.options,m=f.snapTolerance,g=i.offset.left,v=g+p.helperProportions.width,b=i.offset.top,y=b+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--)r=p.snapElements[c].left,h=r+p.snapElements[c].width,l=p.snapElements[c].top,u=l+p.snapElements[c].height,r-m>v||g>h+m||l-m>y||b>u+m||!e.contains(p.snapElements[c].item.ownerDocument,p.snapElements[c].item)?(p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(s=m>=Math.abs(l-y),n=m>=Math.abs(u-b),a=m>=Math.abs(r-v),o=m>=Math.abs(h-g),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||a||o,"outer"!==f.snapMode&&(s=m>=Math.abs(l-b),n=m>=Math.abs(u-y),a=m>=Math.abs(r-g),o=m>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=s||n||a||o||d)}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,i=this.data("ui-draggable").options,s=e.makeArray(e(i.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});s.length&&(t=parseInt(e(s[0]).css("zIndex"),10)||0,e(s).each(function(i){e(this).css("zIndex",t+i)}),this.css("zIndex",t+s.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._zIndex&&e(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(e){function t(e,t,i){return e>t&&t+i>e}e.widget("ui.droppable",{version:"1.10.3",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t=this.options,i=t.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(i)?i:function(e){return e.is(i)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var t=0,i=e.ui.ddmanager.droppables[this.options.scope];i.length>t;t++)i[t]===this&&i.splice(t,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){"accept"===t&&(this.accept=e.isFunction(i)?i:function(e){return e.is(i)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"ui-droppable");return t.options.greedy&&!t.options.disabled&&t.options.scope===s.options.scope&&t.accept.call(t.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(t,{offset:t.element.offset()}),t.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(e,i,s){if(!i.offset)return!1;var n,a,o=(e.positionAbs||e.position.absolute).left,r=o+e.helperProportions.width,h=(e.positionAbs||e.position.absolute).top,l=h+e.helperProportions.height,u=i.offset.left,c=u+i.proportions.width,d=i.offset.top,p=d+i.proportions.height;switch(s){case"fit":return o>=u&&c>=r&&h>=d&&p>=l;case"intersect":return o+e.helperProportions.width/2>u&&c>r-e.helperProportions.width/2&&h+e.helperProportions.height/2>d&&p>l-e.helperProportions.height/2;case"pointer":return n=(e.positionAbs||e.position.absolute).left+(e.clickOffset||e.offset.click).left,a=(e.positionAbs||e.position.absolute).top+(e.clickOffset||e.offset.click).top,t(a,d,i.proportions.height)&&t(n,u,i.proportions.width);case"touch":return(h>=d&&p>=h||l>=d&&p>=l||d>h&&l>p)&&(o>=u&&c>=o||r>=u&&c>=r||u>o&&r>c);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions.height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions={width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight})}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e.data(this,"ui-droppable").options.scope===n}),a.length&&(s=e.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}}})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidth<e.width,a=i(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=i(e.width)&&t.minWidth&&t.minWidth>e.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);(function(e){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.3",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,a.widgetName+"-item")===a?(s=t(this),!1):undefined}),t.data(e.target,a.widgetName+"-item")===a&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=t("<style>*{ cursor: "+o.cursor+" !important; }</style>").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+o.scrollSpeed:e.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+o.scrollSpeed:e.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(e.pageY-t(document).scrollTop()<o.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-o.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<o.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+o.scrollSpeed)),e.pageX-t(document).scrollLeft()<o.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-o.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<o.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+o.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=t.left,o=a+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>a&&o>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,a=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return n?this.floating?o&&"right"===o||"down"===a?2:1:a&&("down"===a?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return this.floating&&a?"right"===a&&s||"left"===a&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){var i,s,n,a,o=[],r=[],h=this._connectWith();if(h&&e)for(i=h.length-1;i>=0;i--)for(n=t(h[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&r.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(r.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=r.length-1;i>=0;i--)r[i][0].each(function(){o.push(this)});return t(o)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(u.push([t.isFunction(a.options.items)?a.options.items.call(a.element[0],e,{item:this.currentItem}):t(a.options.items,a.element),a]),this.containers.push(a));for(i=u.length-1;i>=0;i--)for(o=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",o),c.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td> </td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,a,o,r,h,l,c,u,d,p,f=null,m=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],m=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[m].containerCache.over||(this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1);else{for(o=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],a=this.items.length-1;a>=0;a--)t.contains(this.containers[m].element[0],this.items[a].item[0])&&this.items[a].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[a].top,this.items[a].height))&&(u=this.items[a].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[a][l]-c)&&(d=!0,u+=this.items[a][l]),o>Math.abs(u-c)&&(o=Math.abs(u-c),r=this.items[a],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[m])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[m].element,!0),this._trigger("change",s,this._uiHash()),this.containers[m]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[m],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,a=e.pageX,o=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(a=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(a=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)e||s.push(function(t){return function(e){t._trigger("deactivate",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(t){return function(e){t._trigger("out",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(t){var e=0,i={},s={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",s.height=s.paddingTop=s.paddingBottom=s.borderTopWidth=s.borderBottomWidth="show",t.widget("ui.accordion",{version:"1.10.3",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t(),content:this.active.length?this.active.next():t()}},_createIcons:function(){var e=this.options.icons;e&&(t("<span>").addClass("ui-accordion-header-icon ui-icon "+e.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(e.header).addClass(e.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),undefined):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),"disabled"===t&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!e),undefined)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),a=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(t(e.target).attr("tabIndex",-1),t(a).attr("tabIndex",0),a.focus(),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().focus()},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,s=this.options,n=s.heightStyle,a=this.element.parent(),o=this.accordionId="ui-accordion-"+(this.element.attr("id")||++e);this.active=this._findActive(s.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(e){var i=t(this),s=i.attr("id"),n=i.next(),a=n.attr("id");s||(s=o+"-header-"+e,i.attr("id",s)),a||(a=o+"-panel-"+e,n.attr("id",a)),i.attr("aria-controls",a),n.attr("aria-labelledby",s)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(s.event),"fill"===n?(i=a.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.headers.each(function(){i-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===n&&(i=0,this.headers.next().each(function(){i=Math.max(i,t(this).css("height","").height())}).height(i))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?t():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?t():n,newPanel:r};e.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",e,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?t():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-expanded":"false","aria-hidden":"true"}),s.prev().attr("aria-selected","false"),i.length&&s.length?s.prev().attr("tabIndex",-1):i.length&&this.headers.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(t,e,n){var a,o,r,h=this,l=0,c=t.length&&(!e.length||t.index()<e.index()),u=this.options.animate||{},d=c&&u.down||u,p=function(){h._toggleComplete(n)};return"number"==typeof d&&(r=d),"string"==typeof d&&(o=d),o=o||d.easing||u.easing,r=r||d.duration||u.duration,e.length?t.length?(a=t.show().outerHeight(),e.animate(i,{duration:r,easing:o,step:function(t,e){e.now=Math.round(t)}}),t.hide().animate(s,{duration:r,easing:o,complete:p,step:function(t,i){i.now=Math.round(t),"height"!==i.prop?l+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(a-e.outerHeight()-l),l=0)}}),undefined):e.animate(i,r,o,p):t.animate(s,r,o,p)},_toggleComplete:function(t){var e=t.oldPanel;e.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),e.length&&(e.parent()[0].className=e.parent()[0].className),this._trigger("activate",null,t)}})})(jQuery);(function(t){var e=0;t.widget("ui.autocomplete",{version:"1.10.3",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,undefined;e=!1,s=!1,i=!1;var a=t.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:e=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case a.UP:e=!0,this._keyEvent("previous",n);break;case a.DOWN:e=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),undefined):(this._searchTimeout(t),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(t),this._change(t),undefined)}}),this._initSource(),this.menu=t("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];t(e.target).closest(".ui-menu-item").length||this._delay(function(){var e=this;this.document.one("mousedown",function(s){s.target===e.element[0]||s.target===i||t.contains(i,s.target)||e.close()})})},menufocus:function(e,i){if(this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",e,{item:s})?e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=t("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e||(e=this.element.closest(".ui-front")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):undefined},_search:function(t){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var t=this,i=++e;return function(s){i===e&&t.__response(s),t.pending--,t.pending||t.element.removeClass("ui-autocomplete-loading")}},__response:function(t){t&&(t=this._normalize(t)),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(e){return e.length&&e[0].label&&e[0].value?e:t.map(e,function(e){return"string"==typeof e?{label:e,value:e}:t.extend({label:e.label||e.value,value:e.value||e.label},e)})},_suggest:function(e){var i=this.menu.element.empty();this._renderMenu(i,e),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(t.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(e,i){var s=this;t.each(i,function(t,i){s._renderItemData(e,i)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(e,i){return t("<li>").append(t("<a>").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[t](e),undefined):(this.search(null,e),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var e;this._superApply(arguments),this.options.disabled||this.cancelSearch||(e=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.text(e))}})})(jQuery);(function(t){var e,i,s,n,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",h=function(){var e=t(this);setTimeout(function(){e.find(":ui-button").button("refresh")},1)},l=function(e){var i=e.name,s=e.form,n=t([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?t(s).find("[name='"+i+"']"):t("[name='"+i+"']",e.ownerDocument).filter(function(){return!this.form})),n};t.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,c="checkbox"===this.type||"radio"===this.type,u=c?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===e&&t(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||t(this).removeClass(u)}).bind("click"+this.eventNamespace,function(t){r.disabled&&(t.preventDefault(),t.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),c&&(this.element.bind("change"+this.eventNamespace,function(){n||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(t){r.disabled||(n=!1,i=t.pageX,s=t.pageY)}).bind("mouseup"+this.eventNamespace,function(t){r.disabled||(i!==t.pageX||s!==t.pageY)&&(n=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||n?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||n)return!1;t(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var e=o.element[0];l(e).not(e).map(function(){return t(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(t(this).addClass("ui-state-active"),e=this,o.document.one("mouseup",function(){e=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(t(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(e){return r.disabled?!1:((e.keyCode===t.ui.keyCode.SPACE||e.keyCode===t.ui.keyCode.ENTER)&&t(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){t(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===t.ui.keyCode.SPACE&&t(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var t,e,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(t=this.element.parents().last(),e="label[for='"+this.element.attr("id")+"']",this.buttonElement=t.find(e),this.buttonElement.length||(t=t.length?t.siblings():this.element.siblings(),this.buttonElement=t.filter(e),this.buttonElement.length||(this.buttonElement=t.find(e))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(t,e){return this._super(t,e),"disabled"===t?(e?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var e=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");e!==this.options.disabled&&this._setOption("disabled",e),"radio"===this.type?l(this.element[0]).each(function(){t(this).is(":checked")?t(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):t(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var e=this.buttonElement.removeClass(r),i=t("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(e.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push("ui-button-text-icon"+(n?"s":s.primary?"-primary":"-secondary")),s.primary&&e.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&e.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(a.push(n?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||e.attr("title",t.trim(i)))):a.push("ui-button-text-only"),e.addClass(a.join(" "))}}),t.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(t,e){"disabled"===t&&this.buttons.button("option",t,e),this._super(t,e)},refresh:function(){var e="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(e?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(e?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(a.inline?e.parent()[0]:a.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.3"}});var a,r="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,a;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),a=this._newInst(t(e),n),a.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,a):n&&this._inlineDatepicker(e,a)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,r,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,a,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=t("<span class='"+this._appendClass+"'>"+r+"</span>"),e[o?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(a?t("<img/>").attr({src:a,alt:n,title:n}):n)),e[o?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,a=new Date(2009,11,20),r=this._get(t,"dateFormat");r.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},a.setMonth(e(this._get(t,r.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(e(this._get(t,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),t.input.attr("size",this._formatDate(t,a).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,a,o){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],r,p)),n(p.settings,a||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,r);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,r),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,a){var r,o,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(r=s||{},"string"==typeof s&&(r={},r[s]=a),c&&(this._curInst===c&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,r),null!==h&&r.dateFormat!==e&&r.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&r.dateFormat!==e&&r.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,o),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,a=t.datepicker._getInst(e.target),r=!0,o=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),r=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",a.dpDiv),n[0]&&t.datepicker._selectDay(e.target,a.selectedMonth,a.selectedYear,n[0]),i=t.datepicker._get(a,"onSelect"),i?(s=t.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),r=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),r=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?1:-1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),r=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?-1:1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),r=e.ctrlKey||e.metaKey;break;default:r=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):r=!1;r&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,a=t.datepicker._getInst(i.target);return t.datepicker._get(a,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(a,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,a,r,o,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),a=s?s.apply(e,[e,i]):{},a!==!1&&(n(i.settings,a),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),o={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),o=t.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,a=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],r=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",r*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),a=e.dpDiv.outerHeight(),r=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-r:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+o?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+o):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,a,o=this._curInst;!o||e&&o!==t.data(e,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){t.datepicker._tidyDialog(o)},t.effects&&(t.effects.effect[i]||t.effects[i])?o.dpDiv.hide(i,t.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(e,i,s,n){var a,r=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(a=this._getInst(r[0]),a.selectedDay=a.currentDay=t("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(e,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,a=this._get(e,"altField");a&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(a).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var a,r,o,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,m=(n?n.monthNames:null)||this._defaults.monthNames,g=-1,v=-1,_=-1,b=-1,y=!1,x=function(t){var e=i.length>a+1&&i.charAt(a+1)===t;return e&&a++,e},k=function(t){var e=x(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),a=s.substring(l).match(n);if(!a)throw"Missing number at position "+l;return l+=a[0].length,parseInt(a[0],10)},w=function(i,n,a){var r=-1,o=t.map(x(i)?a:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(o,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(r=i[0],l+=n.length,!1):e}),-1!==r)return r+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(a))throw"Unexpected literal at position "+l;l++};for(a=0;i.length>a;a++)if(y)"'"!==i.charAt(a)||x("'")?D():y=!1;else switch(i.charAt(a)){case"d":_=k("d");break;case"D":w("D",d,p);break;case"o":b=k("o");break;case"m":v=k("m");break;case"M":v=w("M",f,m);break;case"y":g=k("y");break;case"@":h=new Date(k("@")),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((k("!")-this._ticksTo1970)/1e4),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":x("'")?D():y=!0;break;default:D()}if(s.length>l&&(o=s.substr(l),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=g?0:-100)),b>-1)for(v=1,_=b;;){if(r=this._getDaysInMonth(g,v-1),r>=_)break;v++,_-=r}if(h=this._daylightSavingAdjust(new Date(g,v-1,_)),h.getFullYear()!==g||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,a);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),r,o);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),a=n,r=this._getFormatConfig(t);try{a=this.parseDate(i,s,r)||n}catch(o){s=e?"":s}t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),t.currentDay=s?a.getDate():0,t.currentMonth=s?a.getMonth():0,t.currentYear=s?a.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},a=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,a=n.getFullYear(),r=n.getMonth(),o=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":o+=parseInt(l[1],10);break;case"w":case"W":o+=7*parseInt(l[1],10);break;case"m":case"M":r+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r));break;case"y":case"Y":a+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r))}l=h.exec(i)}return new Date(a,r,o)},r=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?s:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,a=t.selectedYear,r=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=r.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=r.getMonth(),t.drawYear=t.selectedYear=t.currentYear=r.getFullYear(),n===t.selectedMonth&&a===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,a,r,o,h,l,c,u,d,p,f,m,g,v,_,b,y,x,k,w,D,T,C,M,S,N,I,P,A,z,H,E,F,O,W,j,R=new Date,L=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),J=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),Q=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),U=this._get(t,"stepMonths"),q=1!==Q[0]||1!==Q[1],X=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),$=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),$)for(e=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-Q[0]*Q[1]+1,$.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-U,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+U,1)),this._getFormatConfig(t)):n,a=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",r=this._get(t,"currentText"),o=this._get(t,"gotoCurrent")&&t.currentDay?X:L,r=K?this.formatDate(r,o,this._getFormatConfig(t)):r,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(t,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),m=this._get(t,"monthNamesShort"),g=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;Q[0]>k;k++){for(w="",this.maxRows=4,D=0;Q[1]>D;D++){if(T=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),C=" ui-corner-all",M="",q){if(M+="<div class='ui-datepicker-group",Q[1]>1)switch(D){case 0:M+=" ui-datepicker-group-first",C=" ui-corner-"+(Y?"right":"left");break;case Q[1]-1:M+=" ui-datepicker-group-last",C=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",C=""}M+="'>"}for(M+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&0===k?Y?a:s:"")+(/all|right/.test(C)&&0===k?Y?s:a:"")+this._generateMonthYearHeader(t,Z,te,G,$,k>0||D>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",S=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+c)%7,S+="<th"+((x+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[N]+"'>"+p[N]+"</span></th>";for(M+=S+"</tr></thead><tbody>",I=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,I)),P=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((P+I)/7),z=q?this.maxRows>A?this.maxRows:A:A,this.maxRows=z,H=this._daylightSavingAdjust(new Date(te,Z,1-P)),E=0;z>E;E++){for(M+="<tr>",F=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",x=0;7>x;x++)O=g?g.apply(t.input?t.input[0]:null,[H]):[!0,""],W=H.getMonth()!==Z,j=W&&!_||!O[0]||G&&G>H||$&&H>$,F+="<td class='"+((x+c+6)%7>=5?" ui-datepicker-week-end":"")+(W?" ui-datepicker-other-month":"")+(H.getTime()===T.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===T.getTime()?" "+this._dayOverClass:"")+(j?" "+this._unselectableClass+" ui-state-disabled":"")+(W&&!v?"":" "+O[1]+(H.getTime()===X.getTime()?" "+this._currentClass:"")+(H.getTime()===L.getTime()?" ui-datepicker-today":""))+"'"+(W&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"'")+"'")+(j?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(W&&!v?" ":j?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===L.getTime()?" ui-state-highlight":"")+(H.getTime()===X.getTime()?" ui-state-active":"")+(W?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=F+"</tr>"}Z++,Z>11&&(Z=0,te++),M+="</tbody></table>"+(q?"</div>"+(Q[0]>0&&D===Q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=M}y+=w}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,a,r,o){var h,l,c,u,d,p,f,m,g=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(a||!g)y+="<span class='ui-datepicker-month'>"+r[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+o[c]+"</option>");y+="</select>"}if(_||(b+=y+(!a&&g&&v?"":" ")),!t.yearshtml)if(t.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10); +return isNaN(e)?d:e},f=p(u[0]),m=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!a&&g&&v?"":" ")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),a=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),r=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,a)));t.selectedDay=r.getDate(),t.drawMonth=t.selectedMonth=r.getMonth(),t.drawYear=t.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),a=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(t,a)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),a=this._getMinMaxDate(t,"max"),r=null,o=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=s),i[1].match(/[+\-].*/)&&(o+=s)),(!n||e.getTime()>=n.getTime())&&(!a||e.getTime()<=a.getTime())&&(!r||e.getFullYear()>=r)&&(!o||o>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.3"})(jQuery);(function(t){var e={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};t.widget("ui.dialog",{version:"1.10.3",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var i=t(this).css(e).offset().top;0>i&&t(this).css("top",e.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog},disable:t.noop,enable:t.noop,close:function(e){var i=this;this._isOpen&&this._trigger("beforeClose",e)!==!1&&(this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||t(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,e){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!e&&this._trigger("focus",t),i},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=t(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var t=this.element.find("[autofocus]");t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).focus()},_keepFocus:function(e){function i(){var e=this.document[0].activeElement,i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),undefined;if(e.keyCode===t.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(n.focus(1),e.preventDefault()):(s.focus(1),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=t("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(e),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title||t.html(" "),t.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=t("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(t.each(i,function(i,s){var n,a;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(e.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,t("<button></button>",s).button(a).appendTo(e.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){t(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,e(n))},drag:function(t,s){i._trigger("drag",t,e(s))},stop:function(n,a){s.position=[a.position.left-i.document.scrollLeft(),a.position.top-i.document.scrollTop()],t(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,e(a))}})},_makeResizable:function(){function e(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){t(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,e(n))},resize:function(t,s){i._trigger("resize",t,e(s))},stop:function(n,a){s.height=t(this).height(),s.width=t(this).width(),t(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,e(a))}}).css("position",a)},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(s){var n=this,a=!1,o={};t.each(s,function(t,s){n._setOption(t,s),t in e&&(a=!0),t in i&&(o[t]=s)}),a&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",o)},_setOption:function(t,e){var i,s,n=this.uiDialog;"dialogClass"===t&&n.removeClass(this.options.dialogClass).addClass(e),"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:""+e}),"draggable"===t&&(i=n.is(":data(ui-draggable)"),i&&!e&&n.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&(s=n.is(":data(ui-resizable)"),s&&!e&&n.resizable("destroy"),s&&"string"==typeof e&&n.resizable("option","handles",e),s||e===!1||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var e=t(this);return t("<div>").css({position:"absolute",width:e.outerWidth(),height:e.outerHeight()}).appendTo(e.parent()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(e){return t(e.target).closest(".ui-dialog").length?!0:!!t(e.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var e=this,i=this.widgetFullName;t.ui.dialog.overlayInstances||this._delay(function(){t.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(s){e._allowInteraction(s)||(s.preventDefault(),t(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=t("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),t.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(t.ui.dialog.overlayInstances--,t.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),t.ui.dialog.overlayInstances=0,t.uiBackCompat!==!1&&t.widget("ui.dialog",t.ui.dialog,{_position:function(){var e,i=this.options.position,s=[],n=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(s=i.split?i.split(" "):[i[0],i[1]],1===s.length&&(s[1]=s[0]),t.each(["left","top"],function(t,e){+s[t]===s[t]&&(n[t]=s[t],s[t]=e)}),i={my:s[0]+(0>n[0]?n[0]:"+"+n[0])+" "+s[1]+(0>n[1]?n[1]:"+"+n[1]),at:s.join(" ")}),i=t.extend({},t.ui.dialog.prototype.options.position,i)):i=t.ui.dialog.prototype.options.position,e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.position(i),e||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.3",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(e),i.has(".ui-menu").length?this.expand(e):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,h=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:h=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}h&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery);(function(t,e){t.widget("ui.progressbar",{version:"1.10.3",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):this.range=t([])},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,h,l,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),h=a.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-a.width()/2,top:e.pageY-h.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i,!0))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](u,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.3",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.3",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),u=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),u&&l.data("ui-tabs-aria-controls",u),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),u={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,u))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,a=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=a),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function a(t){l.of=t,o.is(":hidden")||o.position(l)}var o,r,h,l=t.extend({},this.options.position);if(n){if(o=this._find(s),o.length)return o.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),o=this._tooltip(s),e(s,o.attr("id")),o.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:a}),a(i)):o.position(t.extend({of:s},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(a(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:o}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(o)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),a=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),a.stop(!0),this._hide(a,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:a}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);(function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(t,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[c[l].cache]=o[c[l].cache],n=s._rgba=o._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,a.transparent),s):a[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],l=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=l.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),l.fn=t.extend(l.prototype,{parse:function(n,o,r,h){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(o),o=e);var u=this,d=t.type(n),p=this._rgba=[];return o!==e&&(n=[n,o,r,h],d="array"),"string"===d?this.parse(s(n)||a._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof l?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var a=s.cache;f(s.props,function(t,e){if(!u[a]&&s.to){if("alpha"===t||null==n[t])return;u[a]=s.to(u._rgba)}u[a][e.idx]=i(n[t],e,!0)}),u[a]&&0>t.inArray(null,u[a].slice(0,3))&&(u[a][3]=1,s.from&&(u._rgba=s.from(u[a])))}),this):e},is:function(t){var i=l(t),s=!0,n=this;return f(c,function(t,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=l(t),n=s._space(),a=c[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(t,n){var a=n.idx,o=r[a],l=s[a],c=u[n.type]||{};null!==l&&(null===o?h[a]=l:(c.mod&&(l-o>c.mod/2?o+=c.mod:o-l>c.mod/2&&(o-=c.mod)),h[a]=i((l-o)*e+o,n)))}),this[n](h)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(e)._rgba;return l(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,a=t[2]/255,o=t[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,c=r+h,u=.5*c;return e=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=u?l/c:l/(2-c),[Math.round(e)%360,i,u,null==o?1:o]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],a=t[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,e+1/3)),Math.round(255*n(r,o,e)),Math.round(255*n(r,o,e-1/3)),a]},f(c,function(s,n){var a=n.props,o=n.cache,h=n.to,c=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===e)return this[o].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[o].slice();return f(a,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=l(c(d)),n[o]=d,n):l(d)},f(a,function(e,i){l.fn[e]||(l.fn[e]=function(n){var a,o=t.type(n),h="alpha"===e?this._hsla?"hsla":"rgba":s,l=this[h](),c=l[i.idx];return"undefined"===o?c:("function"===o&&(n=n.call(this,c),o=t.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=c+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var a,o,r="";if("transparent"!==n&&("string"!==t.type(n)||(a=s(n)))){if(n=l(a||n),!d.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&o&&o.style;)try{r=t.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(h){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=l(e.elem,i),e.end=l(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},l.hook(o),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},a=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function s(e,i){var s,n,o={};for(s in i)n=i[s],e[s]!==n&&(a[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(o[s]=n));return o}var n=["add","remove","toggle"],a={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,a,o,r){var h=t.speed(a,o,r);return this.queue(function(){var a,o=t(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var e=t(this);return{el:e,start:i(this)}}),a=function(){t.each(n,function(t,i){e[i]&&o[i+"Class"](e[i])})},a(),l=l.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var e=this,i=t.Deferred(),s=t.extend({},h,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,l.get()).done(function(){a(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),h.complete.call(o[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,a){return s?t.effects.animateClass.call(this,{add:i},s,n,a):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,a){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,a):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,a,o,r){return"boolean"==typeof n||n===e?a?t.effects.animateClass.call(this,n?{add:s}:{remove:s},a,o,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,a,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,a){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,a)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.3",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,a;for(a=0;s.length>a;a++)null!==s[a]&&(n=t.data(i+s[a]),n===e&&(n=""),t.css(s[a],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return e.wrap(s),(e[0]===a||t.contains(e[0],a))&&t(a).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var a=e.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(a)&&a.call(n[0]),t.isFunction(e)&&e()}var n=t(this),a=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):o.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,a=i.queue,o=t.effects.effect[i.effect];return t.fx.off||!o?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):a===!1?this.each(e):this.queue(a||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()})(jQuery);(function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var a,o,r,h=t(this),l=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(h,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",m=i.test(u),g={},v="show"===c;h.parent().is(".ui-effects-wrapper")?t.effects.save(h.parent(),l):t.effects.save(h,l),h.show(),a=t.effects.createWrapper(h).css({overflow:"hidden"}),o=a[p](),r=parseFloat(a.css(f))||0,g[p]=v?o:0,m||(h.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),g[f]=v?r:o+r),v&&(a.css(p,0),m||a.css(f,r+o)),a.animate(g,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&h.hide(),t.effects.restore(h,l),t.effects.removeWrapper(h),n()}})}})(jQuery);(function(t){t.effects.effect.bounce=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(o,e.mode||"effect"),l="hide"===h,c="show"===h,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||l?1:0),m=e.duration/f,g=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=o.queue(),y=b.length;for((c||l)&&r.push("opacity"),t.effects.save(o,r),o.show(),t.effects.createWrapper(o),d||(d=o["top"===v?"outerHeight":"outerWidth"]()/3),c&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,_?2*-d:2*d).animate(a,m,g)),l&&(d/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,o.animate(n,m,g).animate(a,m,g),d=l?2*d:d/2;l&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),o.dequeue()}})(jQuery);(function(t){t.effects.effect.clip=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(o,e.mode||"hide"),l="show"===h,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(o,r),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[d](),l&&(n.css(d,0),n.css(p,a/2)),f[d]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){l||o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","opacity","height","width"],o=t.effects.setMode(n,e.mode||"hide"),r="show"===o,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,a),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===c?-s:s),u[l]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),m||p.hide(),i()}var a,o,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(a=0;u>a;a++)for(h=g.top+a*_,c=a-(u-1)/2,o=0;d>o;o++)r=g.left+o*v,l=o-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(m?l*v:0),top:h+(m?c*_:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:c*_),opacity:m?1:0},e.duration||500,e.easing,s)}})(jQuery);(function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}})(jQuery);(function(t){t.effects.effect.fold=function(e,i){var s,n,a=t(this),o=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(a,e.mode||"hide"),h="show"===r,l="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=h!==d,f=p?["width","height"]:["height","width"],m=e.duration/2,g={},v={};t.effects.save(a,o),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[l?0:1]),h&&s.css(d?{height:0,width:c}:{height:c,width:0}),g[f[0]]=h?n[0]:c,v[f[1]]=h?n[1]:0,s.animate(g,m,e.easing).animate(v,m,e.easing,function(){l&&a.hide(),t.effects.restore(a,o),t.effects.removeWrapper(a),i()})}})(jQuery);(function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],a=t.effects.setMode(s,e.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(o,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&s.hide(),t.effects.restore(s,n),i()}})}})(jQuery);(function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),a=t.effects.setMode(n,e.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(e.times||5)+(h?1:0),c=e.duration/l,u=0,d=n.queue(),p=d.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;l>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,l+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),a="hide"===n,o=parseInt(e.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),a=t.effects.setMode(s,e.mode||"effect"),o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===a?0:100),r=e.direction||"both",h=e.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=e.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*c.y,width:l.width*c.x,outerHeight:l.outerHeight*c.y,outerWidth:l.outerWidth*c.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(o,e.mode||"effect"),f=e.restore||"effect"!==p,m=e.scale||"both",g=e.origin||["middle","center"],v=o.css("position"),_=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===e.mode&&"show"===p?(o.from=e.to||b,o.to=e.from||s):(o.from=e.from||("show"===p?b:s),o.to=e.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(_=_.concat(u),o.from=t.effects.setTransition(o,u,a.from.y,o.from),o.to=t.effects.setTransition(o,u,a.to.y,o.to)),a.from.x!==a.to.x&&(_=_.concat(d),o.from=t.effects.setTransition(o,d,a.from.x,o.from),o.to=t.effects.setTransition(o,d,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(_=_.concat(c).concat(l),o.from=t.effects.setTransition(o,c,a.from.y,o.from),o.to=t.effects.setTransition(o,c,a.to.y,o.to)),t.effects.save(o,_),o.show(),t.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=t.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),l=r.concat(u).concat(d),o.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=t.effects.setTransition(i,u,a.from.y,i.from),i.to=t.effects.setTransition(i,u,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=t.effects.setTransition(i,d,a.from.x,i.from),i.to=t.effects.setTransition(i,d,a.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),t.effects.restore(o,_),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):t.each(["top","left"],function(t,e){o.css(e,function(e,i){var s=parseInt(i,10),n=t?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","height","width"],o=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",h=e.distance||20,l=e.times||3,c=2*l+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),_=v.length;for(t.effects.save(n,a),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+h,m[d]=(p?"+=":"-=")+2*h,g[d]=(p?"-=":"+=")+2*h,n.animate(f,u,e.easing),s=1;l>s;s++)n.animate(m,u,e.easing).animate(g,u,e.easing);n.animate(m,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","width","height"],o=t.effects.setMode(n,e.mode||"show"),r="show"===o,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h,u={};t.effects.save(n,a),n.show(),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,c?isNaN(s)?"-"+s:-s:s),u[l]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),a="fixed"===n.css("position"),o=t("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),i()})}})(jQuery); \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/static/js/respond.min.js b/dspace-jspui/src/main/webapp/static/js/respond.min.js new file mode 100644 index 0000000000000000000000000000000000000000..c341e2b7755d154e155fd4e3f2b77e006362e67a --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/respond.min.js @@ -0,0 +1,11 @@ +/* + * 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/ + */ +window.matchMedia=window.matchMedia||function(a){"use strict";var c,d=a.documentElement,e=d.firstElementChild||d.firstChild,f=a.createElement("body"),g=a.createElement("div");return g.id="mq-test-1",g.style.cssText="position:absolute;top:-100em",f.style.background="none",f.appendChild(g),function(a){return g.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',d.insertBefore(f,e),c=42===g.offsetWidth,d.removeChild(f),{matches:c,media:a}}}(document); + +/*! Respond.js v1.1.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ +(function(a){"use strict";function x(){u(!0)}var b={};a.respond=b,b.update=function(){},b.mediaQueriesSupported=a.matchMedia&&a.matchMedia("only all").matches,b.mediaQueriesSupported;var q,r,t,c=a.document,d=c.documentElement,e=[],f=[],g=[],h={},i=30,j=c.getElementsByTagName("head")[0]||d,k=c.getElementsByTagName("base")[0],l=j.getElementsByTagName("link"),m=[],n=function(){for(var b=0;l.length>b;b++){var c=l[b],d=c.href,e=c.media,f=c.rel&&"stylesheet"===c.rel.toLowerCase();d&&f&&!h[d]&&(c.styleSheet&&c.styleSheet.rawCssText?(p(c.styleSheet.rawCssText,d,e),h[d]=!0):(!/^([a-zA-Z:]*\/\/)/.test(d)&&!k||d.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&m.push({href:d,media:e}))}o()},o=function(){if(m.length){var a=m.shift();v(a.href,function(b){p(b,a.href,a.media),h[a.href]=!0,setTimeout(function(){o()},0)})}},p=function(a,b,c){var d=a.match(/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi),g=d&&d.length||0;b=b.substring(0,b.lastIndexOf("/"));var h=function(a){return a.replace(/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,"$1"+b+"$2$3")},i=!g&&c;b.length&&(b+="/"),i&&(g=1);for(var j=0;g>j;j++){var k,l,m,n;i?(k=c,f.push(h(a))):(k=d[j].match(/@media *([^\{]+)\{([\S\s]+?)$/)&&RegExp.$1,f.push(RegExp.$2&&h(RegExp.$2))),m=k.split(","),n=m.length;for(var o=0;n>o;o++)l=m[o],e.push({media:l.split("(")[0].match(/(only\s+)?([a-zA-Z]+)\s?/)&&RegExp.$2||"all",rules:f.length-1,hasquery:l.indexOf("(")>-1,minw:l.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:l.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},s=function(){var a,b=c.createElement("div"),e=c.body,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",e||(e=f=c.createElement("body"),e.style.background="none"),e.appendChild(b),d.insertBefore(e,d.firstChild),a=b.offsetWidth,f?d.removeChild(e):e.removeChild(b),a=t=parseFloat(a)},u=function(a){var b="clientWidth",h=d[b],k="CSS1Compat"===c.compatMode&&h||c.body[b]||h,m={},n=l[l.length-1],o=(new Date).getTime();if(a&&q&&i>o-q)return clearTimeout(r),r=setTimeout(u,i),void 0;q=o;for(var p in e)if(e.hasOwnProperty(p)){var v=e[p],w=v.minw,x=v.maxw,y=null===w,z=null===x,A="em";w&&(w=parseFloat(w)*(w.indexOf(A)>-1?t||s():1)),x&&(x=parseFloat(x)*(x.indexOf(A)>-1?t||s():1)),v.hasquery&&(y&&z||!(y||k>=w)||!(z||x>=k))||(m[v.media]||(m[v.media]=[]),m[v.media].push(f[v.rules]))}for(var B in g)g.hasOwnProperty(B)&&g[B]&&g[B].parentNode===j&&j.removeChild(g[B]);for(var C in m)if(m.hasOwnProperty(C)){var D=c.createElement("style"),E=m[C].join("\n");D.type="text/css",D.media=C,j.insertBefore(D,n.nextSibling),D.styleSheet?D.styleSheet.cssText=E:D.appendChild(c.createTextNode(E)),g.push(D)}},v=function(a,b){var c=w();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))},w=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}();n(),b.update=n,a.addEventListener?a.addEventListener("resize",x,!1):a.attachEvent&&a.attachEvent("onresize",x)})(this); diff --git a/dspace-jspui/src/main/webapp/static/js/submission-lookup.js b/dspace-jspui/src/main/webapp/static/js/submission-lookup.js new file mode 100644 index 0000000000000000000000000000000000000000..ada12b5b1b7069fcd246044f4f484db648ffcbd9 --- /dev/null +++ b/dspace-jspui/src/main/webapp/static/js/submission-lookup.js @@ -0,0 +1,288 @@ +/* + * 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/ + */ +submissionLookupIdentifiers = function(identInputs){ + var mydata = new Object(); + mydata['s_uuid'] = j('#suuid-identifier').val(); + mydata['type'] = 'identifiers'; + for (var i=0;i<identInputs.length;i++) + { + mydata[j(identInputs[i]).attr('id')] = j(identInputs[i]).val(); + } + var ajaxCall = j.ajax({url: dspaceContextPath+"/json/submissionLookup", + type: "POST", + dataType: "json", + async: true, + contentType: "application/x-www-form-urlencoded;charset=UTF-8", + data: mydata, + error: function(info){ + j('#loading-search-result').modal("hide"); + var message = j('#jserrormessage').text(); + alert(message); + }, + success: function(info) { + if (info == null || info.result == null || info.result.length == 0) + { + j('#result-list').hide(); + j('#empty-result').show(); + } + else + { + submissionLookupShowResult(info, "-identifier"); + } + j('#loading-search-result').modal("hide"); + j('#tabs').find('a[href="#tabs-result"]').click(); + } + }); + j('#loading-search-result').data('ajaxCall', ajaxCall); + j('#loading-search-result').modal("show"); +} + +submissionLookupSearch = function(){ + var mydata = new Object(); + mydata['s_uuid'] = j('#suuid-search').val(); + mydata['type'] = 'search'; + mydata['title'] = j('#search_title').val(); + mydata['authors'] = j('#search_authors').val(); + mydata['year'] = j('#search_year').val(); + var ajaxCall = j.ajax({url: dspaceContextPath+"/json/submissionLookup", + type: "POST", + dataType: "json", + async: true, + contentType: "application/x-www-form-urlencoded;charset=UTF-8", + data: mydata, + error: function(info){ + j('#loading-search-result').modal('hide'); + var message = j('#jserrormessage').text(); + alert(message); + }, + success: function(info) { + if (info == null || info.result == null || info.result.length == 0) + { + j('#result-list').hide(); + j('#empty-result').show(); + } + else + { + submissionLookupShowResult(info, "-search"); + } + j('#loading-search-result').modal('hide'); + j('#tabs').find('a[href="#tabs-result"]').click(); + } + }); + j('#loading-search-result').data('ajaxCall', ajaxCall); + j('#loading-search-result').modal('show'); +} + +submissionLookupDetails = function(button, suffixID){ + var uuid = j(button).data('uuid'); + var mydata = new Object(); + var suuidID = 'suuid' + suffixID + mydata['s_uuid'] = j('#'+suuidID).val(); + mydata['type'] = 'details'; + mydata['i_uuid'] = uuid; + j.ajax({url: dspaceContextPath+"/json/submissionLookup", + type: "POST", + dataType: "json", + async: false, + contentType: "application/x-www-form-urlencoded;charset=UTF-8", + data: mydata, + error: function(info){var message = j('#jserrormessage').text();alert(message);}, + success: function(info) { + if (info == null || info.result == null || info.result.uuid != uuid) + { + var message = j('#jserrormessage').text(); + alert(message); + } + else + { + submissionLookupShowDetails(info.result); + } + j('#tabs').find('a[href="#tabs-result"]').click(); + } + }); +} + + +submissionLookupShowResult = function(info, suffixID){ + j('#result-list').show(); + j('#empty-result').hide(); + j('#result-list').html(" "); + for (var i=0;i<info.result.length;i++) + { + var bt = j('<button class="btn btn-info" type="button">').append(j('#jsseedetailsbuttonmessage').text()); + var par = j('<p class="sl-result">'); + var divImg = j('<div class="submission-lookup-providers">'); + par.append(divImg); + for (var k=0;k<info.result[i].providers.length;k++) + { + var prov = info.result[i].providers[k]; + divImg.append(j('<img class="img-thumbnail" src="'+dspaceContextPath+'/image/submission-lookup-small-'+prov+'.jpg">')); + } + par + .append(j('<span class="sl-result-title">').text(info.result[i].title)) + .append(j('<span class="sl-result-authors">').text(info.result[i].authors)) + .append(j('<span class="sl-result-date">').text(info.result[i].issued)) + .append(bt); + j('#result-list').append(par); + bt.button(); + bt.data({uuid: info.result[i].uuid}); + bt.click(function(){ + submissionLookupDetails(this, suffixID); + }); + } +} + +submissionLookupShowDetails = function(info){ + + var modalbody = j('#loading-details .modal-body'); + var divImg = j('<div class="submission-lookup-providers">'); + + for (var k=0;k<info.providers.length;k++) + { + var prov = info.providers[k]; + divImg.append(j('<img class="img-thumbnail" src="'+dspaceContextPath+'/image/submission-lookup-small-'+prov+'.jpg">')); + } + modalbody.append(divImg); + var detailsDiv = j('<div class="submission-lookup-details">'); + var details = j('<table class="table">'); + detailsDiv.append(details); + + for (var i=0;i<info.fieldsLabels.length;i++) + { + var fieldName = info.fieldsLabels[i][0]; + var fieldLabel = info.fieldsLabels[i][1]; + var values = info.publication[fieldName]; + var tr = j('<tr>'); + tr.append(j('<td class="submission-lookup-label">').append(fieldLabel)); + var td = j('<td>'); + tr.append(td); + for (var k=0;k<values.length;k++) + { + td.append(j('<span>').text(values[k])); + if (k != values.length-1) + { + td.append('<br>'); + } + } + details.append(tr); + } + modalbody.append(detailsDiv); + + modalbody.append(j('#select-collection-div')); + j('#select-collection').val(info.collection); + + var modalfooter = j('#loading-details .modal-footer'); + var start = j('<button class="btn btn-success" type="button">'); + start.append(j('#jsfilldatabuttonmessage').text()); + start.button(); + start.click(function(){ + var selcolid = j('#select-collection').val(); + if (selcolid != null && selcolid != -1) + { + j('#collectionid').val(selcolid); + j('#iuuid').val(info.uuid); + j('#form-submission').submit(); + } + else + { + j('#no-collection-warn').modal('show'); + j('#loading-details').modal('hide'); + } + }); + modalfooter.append(start); + j('#loading-details').modal('show'); +}; + +submissionLookupFile = function(form){ + + var suuidVal = j('#suuid-loader').val(); + var suuid = j('<input type="hidden" name="s_uuid" value="'+suuidVal+'">'); + var collectionidVal = j('#select-collection-file').val(); + var collectionid = j('<input type="hidden" name="collectionid" value="'+collectionidVal+'">'); + var preview_loader = ""; + if(j('#preview_loader').is (':checked')) { + preview_loader = j('<input type="hidden" name="skip_loader" value="false">'); + } + else { + preview_loader = j('<input type="hidden" name="skip_loader" value="true">'); + } + + var provider_loaderVal = j('#provider_loader').val(); + var provider_loader = j('<input type="hidden" name="provider_loader" value="'+provider_loaderVal+'">'); + + // Create the iframe... + var iframe = j('<iframe name="upload_iframe" id="upload_iframe" style="display: none" />'); + // Add to document... + j("body").append(iframe); + + // Add event... + var eventHandler = function () { + + j('#upload_iframe').off(); + + var clickResultTab = true; + var index = 0; + var iindex = new Array(); + // Message from server... + var json = j.parseJSON(j('#upload_iframe').contents().find('body').text()); + if (json == null || json.result == null || json.result.length == 0) + { + j('#result-list').hide(); + j('#empty-result').show(); + } + else + { + for (var i = 0; i < json.result.length; i++) { + if (json.result[i].skip == true) { + clickResultTab = false; + index = i; + break; + } + iindex[i] = json.result[i].uuid; + } + } + if (clickResultTab) { + submissionLookupShowResult(json, "-loader"); + j('#loading-file-result').modal("hide"); + j('#tabs').find('a[href="#tabs-result"]').click(); + } else { + // skip details + j('#collectionid').val(json.result[index].collectionid); + j('#suuid').val(json.result[index].uuid); + j('#fuuid').val(iindex); + j('#form-submission').submit(); + return false; + } + // Del the iframe... + j('upload_iframe').empty(); + }; + + j('#upload_iframe').on("load", eventHandler); + + // Set properties of form... + form.attr("target", "upload_iframe"); + form.attr("action", dspaceContextPath+"/json/submissionLookup"); + form.attr("method", "post"); + form.attr("enctype", "multipart/form-data"); + form.attr("encoding", "multipart/form-data"); + form.attr("target", "upload_iframe"); + form.attr("file", j('#file_upload').val()); + + j(form).append(suuid); + j(form).append(collectionid); + j(form).append(preview_loader); + j(form).append(provider_loader); + // Submit the form... + form.submit(); + + j('#loading-file-result').modal("show"); + + +}; + + 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/access-step.js b/dspace-jspui/src/main/webapp/submit/access-step.js new file mode 100644 index 0000000000000000000000000000000000000000..6e4417e78b3a422f8b51dab1edcd8bd3b2667e00 --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/access-step.js @@ -0,0 +1,24 @@ +/* + * 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/ + */ +(function() { + jQuery.noConflict(); + jQuery(document).ready(function($) { + $("input[name='open_access_radios']").change(function() { + if ($("#embargo_until_date").attr("disabled") == undefined) { + $("#embargo_until_date").attr("disabled", "disabled"); + $("#reason").attr("disabled", "disabled"); + } else { + $("#embargo_until_date").removeAttr("disabled"); + $("#reason").removeAttr("disabled"); + } + }); + $("#embargo_until_date").datepicker({ + dateFormat: "yy-mm-dd" + }); + }); +})(); diff --git a/dspace-jspui/src/main/webapp/submit/access-step.jsp b/dspace-jspui/src/main/webapp/submit/access-step.jsp new file mode 100644 index 0000000000000000000000000000000000000000..caea7de53d3317e1509fbd20ec80b8a9ce8403e8 --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/access-step.jsp @@ -0,0 +1,118 @@ +<%-- + + 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/ + +--%> +<%-- + - Initial questions for keeping UI as simple as possible. + - + - Attributes to pass in: + - submission.info - the SubmissionInfo object + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ page import="java.util.List" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<%@ page import="org.dspace.app.util.SubmissionInfo" %> +<%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.authorize.AuthorizeManager" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> +<%@ page import="org.dspace.content.Item" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.core.Context" %> +<%@ page import="org.dspace.submit.AbstractProcessingStep" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<% + // Obtain DSpace context + Context context = UIUtil.obtainContext(request); + + //get submission information object + SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); + + // Policies List + List<ResourcePolicy> policies = AuthorizeManager.findPoliciesByDSOAndType(context, subInfo.getSubmissionItem().getItem(), ResourcePolicy.TYPE_CUSTOM); + + boolean advanced = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); + + int error_id = request.getAttribute("error_id") == null ? 0 : ((Integer)request.getAttribute("error_id")).intValue(); + + Item item = subInfo.getSubmissionItem().getItem(); + String discoverableChecked = item.isDiscoverable() ? "" : " checked=\"checked\""; + +%> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.access.title" nocache="true"> + + <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> + + <jsp:include page="/submit/progressbar.jsp" /> +<h2><fmt:message key="jsp.submit.access.title" /></h2> +<% + if (error_id > 0) + { + String key = "jsp.submit.access.error_" + error_id; +%> + <div class="alert alert-warning submitFormWarn"><fmt:message key="<%= key %>"/></div> +<% + } +%> + + + <div class="panel panel-primary"><div class="panel-heading"><fmt:message key="jsp.submit.access.access_setting.heading"/></div> + <div class="panel-body"> + <h3 class="access-setting"><fmt:message key="jsp.submit.access.private_setting.heading"/></h3> + + <div class="row"> + <label class="col-md-2" for="private_option"><fmt:message key="jsp.submit.access.private_setting.label"/></label> + <div class="col-md-10"> + <div class="input-group"> + <span class="input-group-addon"> + <input id="private_option" name="private_option" type="checkbox" value="1" <%= discoverableChecked %>/> + </span> + <span class="form-control"><fmt:message key="jsp.submit.access.private_setting.help"/></span> + </div> + </div> + </div> + + <h3 class="access-setting"><fmt:message key="jsp.submit.access.embargo_setting.heading"/></h3> + + <dspace:access-setting subInfo="<%= subInfo %>" dso="<%= subInfo.getSubmissionItem().getItem() %>" embargo="<%= advanced ? true : false %>" addpolicy="<%= advanced ? true : false %>" /> + </div> + </div> + +<% + if (advanced) + { +%> + <div class="panel panel-info"><div class="panel-heading"><fmt:message key="jsp.submit.access.plist.heading"/></div> + <div id="policies-help" class="container help-block"><fmt:message key="jsp.submit.access.policy_setting.help"/></div> + <dspace:policieslist policies="<%= policies %>" /> + </div> +<% + } +%> + + <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> + <div class="row"> + <%= SubmissionController.getSubmissionParameters(context, request) %> + <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> + </form> + + <script type="text/javascript" src="<%= request.getContextPath() %>/submit/access-step.js"></script> +</dspace:layout> 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-bitstream-access.jsp b/dspace-jspui/src/main/webapp/submit/edit-bitstream-access.jsp new file mode 100644 index 0000000000000000000000000000000000000000..c0ff9ac025505e4c133fe1945690de5275a38f11 --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/edit-bitstream-access.jsp @@ -0,0 +1,96 @@ +<%-- + + 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/ + +--%> +<%-- + - Initial questions for keeping UI as simple as possible. + - + - Attributes to pass in: + - submission.info - the SubmissionInfo object + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ page import="java.util.List" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<%@ page import="org.dspace.app.util.SubmissionInfo" %> +<%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.authorize.AuthorizeManager" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> +<%@ page import="org.dspace.content.Item" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.core.Context" %> +<%@ page import="org.dspace.submit.AbstractProcessingStep" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<% + // Obtain DSpace context + Context context = UIUtil.obtainContext(request); + + //get submission information object + SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); + + // Policies List + List<ResourcePolicy> policies = AuthorizeManager.findPoliciesByDSOAndType(context, subInfo.getBitstream(), ResourcePolicy.TYPE_CUSTOM); + + boolean advanced = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); + + int error_id = request.getAttribute("error_id") == null ? 0 : ((Integer)request.getAttribute("error_id")).intValue(); + + Item item = subInfo.getSubmissionItem().getItem(); + String discarableChecked = item.isDiscoverable() ? "" : " checked=\"checked\""; + +%> + +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.edit-bitstream-access.title" nocache="true"> + + <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> + + <jsp:include page="/submit/progressbar.jsp" /> + +<% + if (error_id > 0) + { + String key = "jsp.submit.access.error_" + error_id; +%> + <div class="submitFormWarn"><fmt:message key="<%= key %>"/></div> +<% + } +%> +<% + if (advanced) + { +%> + <h2 class="alert alert-info"><fmt:message key="jsp.submit.access.plist.heading"/></h2> + + <dspace:policieslist policies="<%= policies %>" /> +<% + } +%> + + <h2 class="alert alert-info"><fmt:message key="jsp.submit.edit-bitstream-access.heading"/></h2> + + <dspace:access-setting subInfo="<%= subInfo %>" dso="<%= subInfo.getBitstream() %>" embargo="<%= advanced ? true : false %>" addpolicy="<%= advanced ? true : false %>" /> + + + <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> + <%= SubmissionController.getSubmissionParameters(context, request) %> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="submit_edit_cancel" value="<fmt:message key="jsp.submit.general.cancel"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_save" value="<fmt:message key="jsp.submit.edit-bitstream-access.save.button"/>" /> + </div> + </form> + + <script type="text/javascript" src="<%= request.getContextPath() %>/submit/access-step.js"></script> +</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/edit-policy.jsp b/dspace-jspui/src/main/webapp/submit/edit-policy.jsp new file mode 100644 index 0000000000000000000000000000000000000000..9bdb53fe9fbe7f4298e9eb301192a448d2a5be6a --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/edit-policy.jsp @@ -0,0 +1,69 @@ +<%-- + + 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/ + +--%> +<%-- + - Initial questions for keeping UI as simple as possible. + - + - Attributes to pass in: + - submission.info - the SubmissionInfo object + - rp - the target resource policy + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ page import="java.util.List" %> +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<%@ page import="org.apache.commons.lang.time.DateFormatUtils" %> +<%@ page import="org.dspace.app.util.SubmissionInfo" %> +<%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.submit.step.AccessStep" %> +<%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> +<%@ page import="org.dspace.core.Context" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<% + // Obtain DSpace context + Context context = UIUtil.obtainContext(request); + + //get submission information object + SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); + + // Policies List + ResourcePolicy rp = (ResourcePolicy) subInfo.get(AccessStep.SUB_INFO_SELECTED_RP); + +%> + +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.access.title" 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.access.edit_policy.heading"/></h1> + + <dspace:access-setting subInfo="<%= subInfo %>" rp="<%= rp %>" embargo="true" /> + + <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> + <%= SubmissionController.getSubmissionParameters(context, request) %> + <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="submit_edit_cancel" value="<fmt:message key="jsp.submit.general.cancel"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_save" value="<fmt:message key="jsp.submit.general.save"/>" /> + </div> + </form> + + <script type="text/javascript" src="<%= request.getContextPath() %>/submit/access-step.js"></script> + +</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-policy.jsp b/dspace-jspui/src/main/webapp/submit/review-policy.jsp new file mode 100644 index 0000000000000000000000000000000000000000..bafa741b1e8f3d81ad1cb71a40621b4fa5a870ed --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/review-policy.jsp @@ -0,0 +1,96 @@ +<%-- + + 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/ + +--%> +<%-- + - Review file upload info + - + - 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="java.util.Date"%> +<%@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" %> +<%@ page import="org.dspace.content.Bitstream" %> +<%@ page import="org.dspace.content.BitstreamFormat" %> +<%@ page import="org.dspace.content.Item" %> +<%@ page import="org.dspace.core.Context" %> +<%@ page import="org.dspace.core.Utils" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="javax.servlet.jsp.PageContext" %> + + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + +<% + request.setAttribute("LanguageSwitch", "hide"); + + //get the step number (for jump-to link) + String stepJump = (String) request.getParameter("submission.jump"); + Boolean isDiscoverable = (Boolean) request.getAttribute("submission.item.isdiscoverable"); + List<ResourcePolicy> rpolicies = (List<ResourcePolicy>)request.getAttribute("submission.item.rpolicies"); + Boolean advanced = (Boolean) request.getAttribute("advancedEmbargo"); +%> + + +<%-- ====================================================== --%> +<%-- REVIEW POLICY --%> +<%-- ====================================================== --%> +<div class="col-md-10"> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><fmt:message key="jsp.submit.access.private_setting.heading"/></span> + <span + class="metadataFieldValue col-md-8"> <% if(isDiscoverable) { %> + <fmt:message + key="jsp.submit.access.private_setting.review.discoverable" /> <% } else { %> + <fmt:message + key="jsp.submit.access.private_setting.review.notdiscoverable" /> <% } %> + </span> + </div> +</div> + +<% if(rpolicies!=null && !rpolicies.isEmpty()) { %> +<div class="col-md-10"> + <% if(advanced) { %> + <div class="row"> + <span class="metadataFieldLabel col-md-10"><fmt:message key="jsp.submit.access.plist.heading"/></span> + </div> + <div class="container row"> + <dspace:policieslist policies="<%= rpolicies %>" showButton="false" /> + </div> + <% } else { %> + <% Date startDate = rpolicies.get(0).getStartDate(); + if(startDate!=null) { %> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><fmt:message key="jsp.submit.access.embargo_setting.heading"/></span> + <span + class="metadataFieldValue col-md-8"> + + <fmt:message key="jsp.submit.access.review.embargoed"><fmt:param><%= startDate %></fmt:param></fmt:message> + </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.access.review.button"/>" /> +</div> \ No newline at end of file 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/start-lookup-submission.jsp b/dspace-jspui/src/main/webapp/submit/start-lookup-submission.jsp new file mode 100644 index 0000000000000000000000000000000000000000..9b42446a81f4cae160513ec9842a0dfabf16fcba --- /dev/null +++ b/dspace-jspui/src/main/webapp/submit/start-lookup-submission.jsp @@ -0,0 +1,469 @@ +<%-- + + 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/ + +--%> +<%-- + - UI page for start of a submission with lookup on external sources. + - + - Required attributes: + - collections - Array of collection objects to show in the drop-down. + collectionID - the collection ID of preference for the user + identifiers2providers + searchProviders + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<%@ page import="org.dspace.content.Collection" %> +<%@ page import="java.lang.Boolean" %> +<%@ page import="java.util.List" %> +<%@ page import="java.util.Map" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" + prefix="c" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<% + String contextPath = "/dspace-jspui"; + request.setAttribute("LanguageSwitch", "hide"); + + //get collections to choose from + Collection[] collections = + (Collection[]) request.getAttribute("collections"); + + //get community handle + int communityId = (Integer) request.getAttribute("collectionID"); + + //check if we need to display the "no collection selected" error + Boolean noCollection = (Boolean) request.getAttribute("no.collection"); + Boolean nosuuid = (Boolean) request.getAttribute("nouuid"); + Boolean expired = (Boolean) request.getAttribute("expired"); + + Map<String, List<String>> identifiers2providers = (Map<String, List<String>>) request.getAttribute("identifiers2providers"); + List<String> searchProviders = (List<String>) request.getAttribute("searchProviders"); + List<String> fileLoaders = (List<String>) request.getAttribute("fileLoaders"); + List<String> identifiers = (List<String>) request.getAttribute("identifiers"); + String uuid = (String) request.getAttribute("s_uuid"); +%> +<c:set var="dspace.layout.head" scope="request"> + <style type="text/css"> + + #link-ricerca-identificatore {cursor: pointer; font-weight: bold; color: #FF6600;} + .sl-result {padding: 10px;} + .sl-result:HOVER {background-color: #5C9CCC;} + .sl-result-title, .sl-result-authors, .sl-result-date {display: block;} + .sl-result-title {font-weight: bold;} + .sl-result-authors {font-style: italic;} + .sl-result-date {margin-bottom: 10px;} + .invalid-value {border: 1px solid #FF6600;} + </style> + <script type='text/javascript'>var dspaceContextPath = "<%=request.getContextPath()%>";</script> +</c:set> +<c:set var="dspace.layout.head.last" scope="request"> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/submission-lookup.js"></script> +</c:set> + +<dspace:layout style="submission" locbar="off" + navbar="off" + titlekey="jsp.submit.start-lookup-submission.title" + nocache="true"> + + <h1><fmt:message key="jsp.submit.start-lookup-submission.heading"/></h1> + <div id="jserrormessage" style="display: none"><fmt:message key="jsp.submit.start-lookup-submission.js.errormessage"/></div> + <div id="jsseedetailsbuttonmessage" style="display: none"><fmt:message key="jsp.submit.start-lookup-submission.js.detailsbuttonmessage"/></div> + <div id="jsfilldatabuttonmessage" style="display: none"><fmt:message key="jsp.submit.start-lookup-submission.js.filldataandstartbuttonmessage"/></div> + +<% if (collections.length > 0) + { + //if no collection was selected, display an error + if((noCollection != null) && (noCollection.booleanValue()==true)) + { +%> + <div class="alert alert-warning"> + <p><fmt:message key="jsp.submit.start-lookup-submission.no-collection"/></p> + </div> +<% + } + //if no collection was selected, display an error + if((nosuuid != null) && (nosuuid.booleanValue()==true)) + { +%> + <div class="alert alert-warning"> + <p><fmt:message key="jsp.submit.start-lookup-submission.nosuuid"/></p> + </div> +<% + } + //if no collection was selected, display an error + if((expired != null) && (expired.booleanValue()==true)) + { +%> + <div class="alert alert-warning"> + <p><fmt:message key="jsp.submit.start-lookup-submission.expired"/></p> + </div> +<% + } +%> + +<div id="tabs"> + <ul class="nav nav-tabs"> + <li class="active"><a href="#tabs-search"><fmt:message key="jsp.submit.start-lookup-submission.tabs.search" /></a></li> + <li><a href="#tabs-result"><fmt:message key="jsp.submit.start-lookup-submission.tabs.result" /></a></li> + </ul> + <div class="tab-content"> + <div class="tab-pane" id="tabs-search"> + + + <div id="tabs-search-accordion"> + <h3><a href="#"><fmt:message key="jsp.submit.start-lookup-submission.manual-submission"/></a></h3> + <div id="manual-accordion"> </div> +<% + if (searchProviders != null && searchProviders.size() > 0) { + %> + <h3><a href="#"><fmt:message key="jsp.submit.start-lookup-submission.search"/></a></h3> + <div id="search-accordion"> + <form class="form-horizontal" id="form-submission-search" action="" method="post"> + <input type="hidden" id="suuid-search" name="suuid" value="<%= uuid %>"/> + <input type="hidden" id="iuuid-search" name="iuuid" value=""/> + <input type="hidden" id="fuuid-search" name="fuuid" value=""/> + <input type="hidden" id="collectionid-search" name="collectionid" value=""/> +<% + for (String provider : searchProviders) + { +%> + <img class="img-thumbnail" src="<%= request.getContextPath() %>/image/submission-lookup-small-<%= provider %>.jpg" /> +<% + } + %> + <p class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.search.hints"/></p> + <div class="form-group"> + <label for="search_title"><fmt:message key="jsp.submit.start-lookup-submission.search.title"/>:</label> + <textarea class="form-control submission-lookup-search" name="search_title" id="search_title" cols="50" row="4"></textarea> + </div> + <div class="form-group"> + <label for="search_year"><fmt:message key="jsp.submit.start-lookup-submission.search.year"/>:</label> + <input class="form-control submission-lookup-search" type="text" size="7" name="search_year" id="search_year" /> + </div> + + <div class="form-group"> + <label for="search_authors"><fmt:message key="jsp.submit.start-lookup-submission.search.authors"/>:</label> + <textarea class="form-control submission-lookup-search" name="search_authors" id="search_authors"cols="50" row="4"></textarea> + </div> + + <div class="row"> + <button type="button" class="btn btn-primary col-md-2 pull-right" id="search_go"><fmt:message key="jsp.submit.start-lookup-submission.search-go"/></button> + </div> + </form> + </div> +<% } %> + + + <h3><a href="#"><fmt:message key="jsp.submit.start-lookup-submission.identifiers"/></a></h3> + <div id="identifier-accordion"> + <form class="form-horizontal" id="form-submission-identifier" action="" method="post"> + <input type="hidden" id="suuid-identifier" name="suuid" value="<%= uuid %>"/> + <input type="hidden" id="iuuid-identifier" name="iuuid" value=""/> + <input type="hidden" id="fuuid-identifier" name="fuuid" value=""/> + <input type="hidden" id="collectionid-identifier" name="collectionid" value=""/> +<% if (identifiers != null && identifiers.size()>0) { + %> + + <p class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.identifiers.hints"/></p> +<% + for (String identifier : identifiers) + { +%> +<c:set var="identifier"><%= identifier %></c:set> + <div class="form-group"> + <label class="col-md-3" for="identifier_<%= identifier%>"><span class="submission-lookup-label"><fmt:message key="jsp.submit.start-lookup-submission.identifier-${identifier}"/>:</span> + <span class="help-block submission-lookup-hint"><fmt:message key="jsp.submit.start-lookup-submission.identifier-${identifier}.hint"/></span></label> + <div class="col-md-9"> + <div class="col-md-4"> + <input class="form-control submission-lookup-identifier" type="text" name="identifier_<%= identifier%>" id="identifier_<%= identifier%>" /> + </div> + <div class="col-md-7"> +<% + for (String provider : identifiers2providers.get(identifier)) + { +%> + + <img class="img-thumbnail" src="<%= request.getContextPath() %>/image/submission-lookup-small-<%= provider %>.jpg" /> + +<% + } +%></div></div></div><% + } %> + <div class="row"> + <button class="btn btn-primary col-md-2 pull-right" type="button" id="lookup_idenfifiers"><fmt:message key="jsp.submit.start-lookup-submission.identifier.lookup"/></button> + </div> + </form> + </div> +<% + + } %> + + <% if (fileLoaders != null && fileLoaders.size()>0) { + %> + <h3><a href="#"><fmt:message key="jsp.submit.start-lookup-submission.byfile"/></a></h3> + <div id="file-accordion" class="container"> + <form class="form-horizontal" id="form-submission-loader" action="" method="post"> + <input type="hidden" id="suuid-loader" name="suuid" value="<%= uuid %>"/> + <input type="hidden" id="iuuid-loader" name="iuuid" value=""/> + <input type="hidden" id="fuuid-loader" name="fuuid" value=""/> + <input type="hidden" id="collectionid-loader" name="collectionid" value=""/> + <p class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.byfile.hints"/></p> + + <div class="form-group"> + <label class="col-md-3" for="provider_loader"><span class="submission-lookup-label"><fmt:message key="jsp.submit.start-lookup-submission.byfile.chooseprovider"/>:</span></label> + <div class="col-md-6"> + <select class="form-control submission-file-loader" name="provider_loader" id="provider_loader"> + <option value="-1"><fmt:message key="jsp.submit.start-lookup-submission.select.collection.defaultoption"/></option> + <% + for (String dataLoader : fileLoaders) + { + %> + <option value="<%= dataLoader %>"><%= dataLoader %></option> + <% + } + %> + </select> + </div> + </div> + <div class="form-group"> + <label class="col-md-3" for="file_upload"><fmt:message key="jsp.submit.start-lookup-submission.byfile.file"/>:</label> + <div class="col-md-7"> + <input class="form-control submission-file-loader" type="file" name="file_upload" id="file_upload" /> + </div> + </div> + + <div class="container checkbox"> + <input class="submission-file-loader submission-preview-loader" type="checkbox" name="preview_loader" id="preview_loader" value="<%= Boolean.TRUE%>"/><span class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.byfile.filepreview"/></span> + </div> + + <div class="form-group" id="select-collection-file-div"> + <label class="col-md-3" for="select-collection-file"><fmt:message key="jsp.submit.start-lookup-submission.byfile.filecollection"/>:</label> + <div class="col-md-6"> + <select class="form-control submission-file-loader" name="select-collection-file" id="select-collection-file"> + <% for (Collection c : collections) { %> + <option value="<%= c.getID() %>"><%= c.getName() %></option> + <% } %> + </select> + </div> + </div> + <button class="btn btn-primary col-md-2 pull-right" type="button" id="loadfile_go"><fmt:message key="jsp.submit.start-lookup-submission.byfile.process"/></button> + </form> + </div> +<% + + } %> + + </div> + +</div> + +<div class="tab-pane" id="tabs-result"> + <div id="empty-result"> + <p class="alert alert-warning"><fmt:message key="jsp.submit.start-lookup-submission.noresult"/></p> + </div> + <div id="result-list"></div> + <div id="manual-submission"> + <div class="form-group"> + <div class="col-md-3"> + <label for="select-collection-manual"><fmt:message key="jsp.submit.start-lookup-submission.select.collection.label"/></label> + </div> + <div class="col-md-7"> + <select class="form-control" id="select-collection-manual"> + <option value="-1"><fmt:message key="jsp.submit.start-lookup-submission.select.collection.defaultoption"/></option> + <% for (Collection c : collections) { %> + <option value="<%= c.getID() %>"><%= c.getName() %></option> + <% } %> + </select> + </div> + </div> + <form class="form-horizontal" id="form-submission" action="" method="post"> + <input type="hidden" id="iuuid" name="iuuid" value=""/> + <input type="hidden" id="fuuid" name="fuuid" value=""/> + <input type="hidden" id="suuid" name="suuid" value="<%= uuid %>"/> + <input type="hidden" id="collectionid" name="collectionid" value=""/> + <div class="btn-group"> + <button class="btn btn-success col-md-offset-5" id="manual-submission-button" type="button"><fmt:message key="jsp.submit.start-lookup-submission.button.manual-submission"/> </button> + </div> + </form> + </div> + </div> + <div class="row container"> + <button type="button" class="btn btn-default col-md-2 pull-right exit"><fmt:message key="jsp.submit.start-lookup-submission.exit"/></button> + </div> +</div> +</div> + <div id="hidden-area" style="display: none;"> + <div id="select-collection-div"> + <select class="form-control" id="select-collection"> + <% for (Collection c : collections) { %> + <option value="<%= c.getID() %>"><%= c.getName() %></option> + <% } %> + </select> + </div> + </div> + + +<div id="no-collection-warn" class="modal"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><fmt:message key="jsp.submit.start-lookup-submission.no-collection-warn.title" /></h4> + </div> + <div class="modal-body"> + <p class="alert alert-warning"><fmt:message key="jsp.submit.start-lookup-submission.no-collection-warn.hint" /></p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal"><fmt:message key="jsp.submit.start-lookup-submission.no-collection.dialog.return" /></button> + </div> + </div><!-- /.modal-content --> + </div><!-- /.modal-dialog --> +</div><!-- /.modal --> + +<div id="loading-search-result" class="modal"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><fmt:message key="jsp.submit.start-lookup-submission.search-loading.title" /></h4> + </div> + <div class="modal-body"> + <p class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.search-loading.hint" /></p> + </div> + <div class="modal-footer"> + <img src="<%= request.getContextPath() %>/sherpa/image/ajax-loader-big.gif"/> + </div> + </div><!-- /.modal-content --> + </div><!-- /.modal-dialog --> +</div><!-- /.modal --> + +<div id="loading-file-result" class="modal"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><fmt:message key="jsp.submit.start-lookup-submission.search-loading.title" /></h4> + </div> + <div class="modal-body"> + <p class="help-block"><fmt:message key="jsp.submit.start-lookup-submission.search-loading.hint" /></p> + </div> + <div class="modal-footer"> + <img src="<%= request.getContextPath() %>/sherpa/image/ajax-loader-big.gif"/> + </div> + </div><!-- /.modal-content --> + </div><!-- /.modal-dialog --> +</div><!-- /.modal --> + +<div id="loading-details" class="modal"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><fmt:message key="jsp.submit.start-lookup-submission.js.titlepopupmessage" /></h4> + </div> + <div class="modal-body"> + + </div> + <div class="modal-footer"> + + </div> + </div><!-- /.modal-content --> + </div><!-- /.modal-dialog --> +</div><!-- /.modal --> + +<% } else { %> + <p class="submitFormWarn"><fmt:message key="jsp.submit.select-collection.none-authorized"/></p> +<% } %> + <br/> + <p><fmt:message key="jsp.general.goto"/><br /> + <a href="<%= request.getContextPath() %>"><fmt:message key="jsp.general.home"/></a><br /> + <a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.general.mydspace" /></a> + </p> + <script type="text/javascript"><!-- + var j = jQuery.noConflict(); + j("#tabs").tabs({ + beforeActivate: function( event, ui ) { + if ('tabs-result' == j(ui.newPanel).attr('id')) + { + j('#manual-submission').appendTo(j(ui.newPanel)); + } + else + { + j('#manual-submission').appendTo(j('#manual-accordion')); + } + } + }); + j('#tabs-search-accordion').accordion({ + heightStyle: "content", + collapsible: true, + active: false, + beforeActivate: function( event, ui ) { + if ('manual-accordion' == ui.newPanel.attr('id')) + { + j('#manual-submission').appendTo(ui.newPanel); + } + } + }); + j('#link-ricerca-identificatore').click(function(){ + j('#tabs-search-accordion').accordion({'active': 2}); + }); + j('button').button(); + j('#manual-submission-button').click(function(event){ + var colman = j('#select-collection-manual').val(); + if (colman != -1) + { + j('#collectionid').val(colman); + j('#form-submission').submit(); + } + else + { + j('#no-collection-warn').modal('show'); + } + }); + j('#lookup_idenfifiers').click(function(){ + submissionLookupIdentifiers(j('input.submission-lookup-identifier')); + }); + j('#search_go').click(function(){ + submissionLookupSearch(j('.submission-lookup-search')); + }); + j('#loadfile_go').click(function(){ + j('#select-collection').val(j('#select-collection-file').val()); + submissionLookupFile(j('#form-submission-loader')); + }); + j('button.exit').click(function(event){ + event.preventDefault(); + window.location = "<%= request.getContextPath() %>/mydspace"; + }); + j('#loading-search-result').on('hide.bs.modal', function () { + j(this).data('ajaxCall').abort(); + }); + j('#loading-details').on('hidden.bs.modal', function () { + j('#hidden-area').append(j('#select-collection-div')); + j('#loading-details .modal-body').empty(); + j('#loading-details .modal-footer').empty(); + }); + j(".submission-preview-loader").click(function() { + if(j(this).is (':checked')) { + j("#select-collection-file-div").hide(); + } + else { + j("#select-collection-file-div").show(); + } + }); + j('#tabs-search-accordion').accordion({'active': 0}); + --></script> + +</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/confirm-privating-item.jsp b/dspace-jspui/src/main/webapp/tools/confirm-privating-item.jsp new file mode 100644 index 0000000000000000000000000000000000000000..18a8fc3703f629be0def73de8cbf313d1f62d0a6 --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/confirm-privating-item.jsp @@ -0,0 +1,64 @@ +<%-- + + 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/ + +--%> +<%-- + - Confirm privating of a item + - + - Attributes: + - item - item we may withdraw + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ page import="org.dspace.app.webui.servlet.admin.EditItemServlet" %> +<%@ page import="org.dspace.content.Item" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<% + String handle = (String) request.getAttribute("handle"); + Item item = (Item) request.getAttribute("item"); + request.setAttribute("LanguageSwitch", "hide"); +%> + +<dspace:layout titlekey="jsp.tools.confirm-privating-item.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin" + nocache="true"> + + <h1><fmt:message key="jsp.tools.confirm-privating-item.title"/>: <%= (handle == null ? String.valueOf(item.getID()) : handle) %></h1> + + <p><fmt:message key="jsp.tools.confirm-privating-item.question"/></p> + + <dspace:item item="<%= item %>" style="full" /> + + <form method="post" action=""> + <input type="hidden" name="item_id" value="<%= item.getID() %>"/> + <input type="hidden" name="action" value="<%= EditItemServlet.CONFIRM_PRIVATING %>"/> + + <center> + <table width="70%"> + <tr> + <td align="left"> + <input type="submit" name="submit" value="<fmt:message key="jsp.tools.confirm-privating-item.privating.button"/>" /> + </td> + <td align="right"> + <%-- <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> + </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/curate-collection.jsp b/dspace-jspui/src/main/webapp/tools/curate-collection.jsp new file mode 100644 index 0000000000000000000000000000000000000000..10cfe6db1396d2ed7e473db80e156eeb90e04c19 --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/curate-collection.jsp @@ -0,0 +1,95 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - collection - the collection + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Collection" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Collection collection = (Collection) request.getAttribute("collection"); + int collectionID = (collection != null ? collection.getID() : -1); + int communityID = (collection.getParentObject() != null ? collection.getParentObject().getID() : -1); + String title = (collection != null ? collection.getMetadata("name") : "Unknown Collection"); + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.tools.curate.collection.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/tools/curate-message.jsp" %> + + <h1><fmt:message key="jsp.tools.curate.collection.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + <div class="row container"> + <form action="<%=request.getContextPath()%>/tools/curate" method="post"> + +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <label for="select_curate_group"><fmt:message key="jsp.tools.curate.select-group.tag"/></label>: + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> +<% + } +%> + <div class="input-group"> + <label for="curate_task" class="input-group-addon"><fmt:message key="jsp.tools.curate.select-task.tag"/>:</label> + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + <input type="hidden" name="collection_id" value="<%= collectionID %>"/> + </div> + <br/> + <div class="col-md-4 row pull-right"> + <input class="btn btn-warning col-md-6" type="submit" name="submit_collection_queue" value="<fmt:message key="jsp.tools.curate.queue.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_collection_curate" value="<fmt:message key="jsp.tools.curate.perform.button"/>" /> + </div> + </form> + </div> + <br/> + <div class="row container"> + <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="collection_id" value="<%= collectionID %>"/> + <input type="hidden" name="community_id" value="<%= communityID %>" /> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_EDIT_COLLECTION %>" /> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.tools.curate.return.collection.button"/>" /> + </form> + </div> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/curate-community.jsp b/dspace-jspui/src/main/webapp/tools/curate-community.jsp new file mode 100644 index 0000000000000000000000000000000000000000..6c26c3d3893d5672fbf73fb0fb2fea547ea1300c --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/curate-community.jsp @@ -0,0 +1,95 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - community - the community + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Community" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Community community = (Community) request.getAttribute("community"); + int communityID = (community != null ? community.getID() : -1); + String title = (community != null ? community.getMetadata("name") : "Unknown Community"); + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.tools.curate.community.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/tools/curate-message.jsp" %> + + <h1><fmt:message key="jsp.tools.curate.community.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + <div class="row container"> + <form action="<%=request.getContextPath()%>/tools/curate" method="post"> + +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + + <label for="select_curate_group"><fmt:message key="jsp.tools.curate.select-group.tag"/></label>: + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> +<% + } +%> + + <div class="input-group"> + <label for="curate_task" class="input-group-addon"><fmt:message key="jsp.tools.curate.select-task.tag"/>:</label> + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + <input type="hidden" name="community_id" value="<%= communityID %>"/> + <br/> + <div class="col-md-4 row pull-right"> + <input class="btn btn-warning col-md-6" type="submit" name="submit_community_queue" value="<fmt:message key="jsp.tools.curate.queue.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_community_curate" value="<fmt:message key="jsp.tools.curate.perform.button"/>" /> + </div> + </form> + </div> + <br/> + <div class="row container"> + <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="community_id" value="<%= communityID %>" /> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_EDIT_COMMUNITY %>" /> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.tools.curate.return.community.button"/>" /> + </form> + </div> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/curate-item.jsp b/dspace-jspui/src/main/webapp/tools/curate-item.jsp new file mode 100644 index 0000000000000000000000000000000000000000..2898b993eaf54b193862c1a903ffb3abaf00e882 --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/curate-item.jsp @@ -0,0 +1,105 @@ +<%-- + + 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/ + +--%> +<%-- + - Form requesting a Handle or internal item ID for item editing + - + - Attributes: + - curate_group_options - options string of gropu selection. + - "" unless ui.taskgroups is set + - curate_task_options - options string of task selection. + - item - the item + - task_result - result of the curation task + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> +<%@ page import="org.dspace.app.webui.util.CurateTaskResult" %> +<%@ page import="org.dspace.content.Item" %> +<%@ page import="org.dspace.content.DCValue" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> +<%! + private static final String TASK_QUEUE_NAME = ConfigurationManager.getProperty("curate", "ui.queuename"); +%> +<% + Item item = (Item) request.getAttribute("item"); + int itemID = (item != null ? item.getID() : -1); + String title = "Unknown Item"; + if (item != null) + { + DCValue[] dcvs = item.getMetadata("dc.title"); + if (dcvs != null && dcvs.length > 0) + { + title = dcvs[0].value; + } + } + String groupOptions = (String)request.getAttribute("curate_group_options"); + String taskOptions = (String)request.getAttribute("curate_task_options"); +%> + +<dspace:layout style="submission" titlekey="jsp.tools.curate.item.title" + navbar="admin" + locbar="link" + parenttitlekey="jsp.administer" + parentlink="/dspace-admin"> + +<%@ include file="/tools/curate-message.jsp" %> + + <h1><fmt:message key="jsp.tools.curate.item.heading"> + <fmt:param value="<%= title %>"/> + </fmt:message> + </h1> + <div class="row container"> + <form action="<%=request.getContextPath()%>/tools/curate" method="post"> +<% + if (groupOptions != null && !"".equals(groupOptions)) + { +%> + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.tools.curate.select-group.tag"/>:</label> + + <select class="form-control" name="select_curate_group" id="select_curate_group" onchange="this.form.submit();"> + <%= groupOptions %> + </select> + </div> +<% + } +%> + + <div class="input-group"> + <label class="input-group-addon"><fmt:message key="jsp.tools.curate.select-task.tag"/>:</label> + <select class="form-control" name="curate_task" id="curate_task"> + <%= taskOptions %> + </select> + </div> + + <br/> + <div class="col-md-4 row pull-right"> + <input type="hidden" name="item_id" value="<%= itemID %>"/> + <input class="btn btn-warning col-md-6" type="submit" name="submit_item_queue" value="<fmt:message key="jsp.tools.curate.queue.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="submit_item_curate" value="<fmt:message key="jsp.tools.curate.perform.button"/>" /> + </div> + + </form> + </div> + <div class="row container"> + <form method="get" action="<%=request.getContextPath()%>/tools/edit-item"> + <input type="hidden" name="item_id" value="<%= itemID %>"/> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.tools.curate.return.item.button"/>"/> + </form> + </div> + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/curate-message.jsp b/dspace-jspui/src/main/webapp/tools/curate-message.jsp new file mode 100644 index 0000000000000000000000000000000000000000..7bb3000eab3a80a298b518829d76c3a4095f943a --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/curate-message.jsp @@ -0,0 +1,82 @@ +<%-- + + 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/ + +--%> +<% + CurateTaskResult result = (CurateTaskResult) request.getAttribute("task_result"); + if (result != null) + { + String type = result.getType(); + boolean isSuccess = result.isSuccess(); + String resultClass = (isSuccess ? "success" : "danger"); +%> + <div class="alert alert-<%= resultClass %>"> + <b> + <fmt:message key="jsp.tools.curate.task.name"> + <fmt:param value="<%= result.getTask() %>"/> + </fmt:message> + </b> +<% + if ("perform".equals(type)) + { + if (isSuccess) + { +%> + <p class="task-result"><fmt:message key="jsp.tools.curate.perform.success"/></p> + <div class="task-message"> + <fmt:message key="jsp.tools.curate.perform.message.success"> + <fmt:param value="<%= result.getStatus() %>"/> + <fmt:param value="<%= result.getResult() %>"/> + </fmt:message> + </div> +<% + } + else + { +%> + <p class="task-result"><fmt:message key="jsp.tools.curate.perform.failure"/></p> + <div class="task-message"> + <fmt:message key="jsp.tools.curate.perform.message.success"> + <fmt:param value="<%= result.getResult() %>"/> + </fmt:message> + </div> +<% + } + } + else + { + if (isSuccess) + { +%> + <p class="task-result"><fmt:message key="jsp.tools.curate.queue.success"/></p> + <div class="task-message"> + <fmt:message key="jsp.tools.curate.queue.message.success"> + <fmt:param value="<%= result.getHandle() %>"/> + <fmt:param value="<%= TASK_QUEUE_NAME %>"/> + </fmt:message> + </div> +<% + } + else + { +%> + <p class="task-result"><fmt:message key="jsp.tools.curate.queue.failure"/></p> + <div class="task-message"> + <fmt:message key="jsp.tools.curate.queue.message.failure"> + <fmt:param value="<%= result.getHandle() %>"/> + <fmt:param value="<%= TASK_QUEUE_NAME %>"/> + </fmt:message> + </div> +<% + } + } +%> + </div> +<% + } +%> 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/tools/version-history.jsp b/dspace-jspui/src/main/webapp/tools/version-history.jsp new file mode 100644 index 0000000000000000000000000000000000000000..52bc415973c72b9fa4f6584c2198b8c953d15fe0 --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/version-history.jsp @@ -0,0 +1,121 @@ +<%-- + + 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/ + +--%> +<%-- + - Version history table with functionalities + - + - Attributes: + --%> + +<%@page import="org.dspace.app.webui.util.UIUtil"%> +<%@page import="org.dspace.core.Context"%> +<%@page import="org.dspace.content.Item"%> +<%@page import="org.dspace.eperson.EPerson"%> +<%@page import="org.dspace.versioning.Version"%> +<%@page import="org.dspace.app.webui.util.VersionUtil"%> +<%@page import="org.dspace.versioning.VersionHistory"%> +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + +<% + Integer itemID = (Integer)request.getAttribute("itemID"); + String versionID = (String)request.getAttribute("versionID"); + Item item = (Item) request.getAttribute("item"); + Boolean removeok = UIUtil.getBoolParameter(request, "delete"); + Context context = UIUtil.obtainContext(request); + + request.setAttribute("LanguageSwitch", "hide"); +%> +<c:set var="dspace.layout.head.last" scope="request"> +<script type="text/javascript"> +var j = jQuery.noConflict(); +</script> +</c:set> +<dspace:layout style="submission" titlekey="jsp.version.history.title"> + + <div class="modal fade" id="myModal"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> + <h4 class="modal-title"><fmt:message key="jsp.version.history.delete.warning.head1"/></h4> + </div> + <div class="modal-body"> + <p><fmt:message key="jsp.version.history.delete.warning.para1"/><br/><fmt:message key="jsp.version.history.delete.warning.para2"/></p> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal"><fmt:message key="jsp.version.history.popup.close"/></button> + <button type="button" class="btn btn-danger" onclick="j('#myModal').modal('hide');j('#submit_delete').click();"><fmt:message key="jsp.version.history.popup.delete"/></button> + </div> + </div><!-- /.modal-content --> + </div><!-- /.modal-dialog --> +</div><!-- /.modal --> + + + <h1><fmt:message key="jsp.version.history.head2"/></h1> + + <% if(removeok) { %><div class="alert alert-success"><fmt:message key="jsp.version.history.delete.success.message"/></div><% } %> + <form action="<%= request.getContextPath() %>/tools/history" method="post"> + <input type="hidden" name="itemID" value="<%= itemID %>" /> + <input type="hidden" name="versionID" value="<%= versionID %>" /> + <%-- Versioning table --%> +<% + + VersionHistory history = VersionUtil.retrieveVersionHistory(context, item); + +%> + <div id="versionHistory"> + <p class="alert alert-info"><fmt:message key="jsp.version.history.legend"/></p> + + + <table class="table"> + <tr> + <th id="t0"></th> + <th id="t1" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column1"/></th> + <th + id="t2" class="oddRowOddCol"><fmt:message key="jsp.version.history.column2"/></th> + <th + id="t3" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column3"/></th> + <th + id="t4" class="oddRowOddCol"><fmt:message key="jsp.version.history.column4"/></th> + <th + id="t5" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column5"/> </th> + </tr> + + <% for(Version versRow : history.getVersions()) { + + EPerson versRowPerson = versRow.getEperson(); + String[] identifierPath = VersionUtil.addItemIdentifier(item, versRow); + + %> + <tr> + <td headers="t0"><input type="checkbox" class="remove" name="remove" value="<%=versRow.getVersionId()%>"/></td> + <td headers="t1" class="oddRowEvenCol"><%= versRow.getVersionNumber() %></td> + <td headers="t2" class="oddRowOddCol"><a href="<%= request.getContextPath() + identifierPath[0] %>"><%= identifierPath[1] %></a><%= item.getID()==versRow.getItemID()?"<span class=\"glyphicon glyphicon-asterisk\"></span>":""%></td> + <td headers="t3" class="oddRowEvenCol"><a href="mailto:<%= versRowPerson.getEmail() %>"><%=versRowPerson.getFullName() %></a></td> + <td headers="t4" class="oddRowOddCol"><%= versRow.getVersionDate() %></td> + <td headers="t5" class="oddRowEvenCol"><%= versRow.getSummary() %><a class="btn btn-default pull-right" href="<%= request.getContextPath() %>/tools/version?itemID=<%= versRow.getItemID()%>&versionID=<%= versRow.getVersionId() %>&submit_update_version"><span class="glyphicon glyphicon-pencil"></span> <fmt:message key="jsp.version.history.update"/></a></td> + </tr> + <% } %> + </table> + + <input data-toggle="modal" href="#myModal" class="btn btn-danger" type="button" id="fake_submit_delete" value="<fmt:message key="jsp.version.history.delete"/>"/> <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.version.history.return"/>" name="submit_cancel"/> + </div> + <div style="display: none"> + <input type="submit" value="<fmt:message key="jsp.version.history.delete"/>" name="submit_delete" id="submit_delete"/> + </div> +</form> + + +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/version-summary.jsp b/dspace-jspui/src/main/webapp/tools/version-summary.jsp new file mode 100644 index 0000000000000000000000000000000000000000..7e64a1a6361c7643ddcaf315ad5e733025c72d45 --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/version-summary.jsp @@ -0,0 +1,47 @@ +<%-- + + 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/ + +--%> +<%-- + - Insert summary for versionable item JSP + - + - Attributes: + --%> + +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + + +<% + Integer itemID = (Integer)request.getAttribute("itemID"); + request.setAttribute("LanguageSwitch", "hide"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.version-summary.title"> + + <h1><fmt:message key="jsp.dspace-admin.version-summary.heading"/></h1> + + <form action="<%= request.getContextPath() %>/tools/version" method="post"> + <input type="hidden" name="itemID" value="<%= itemID %>" /> + <p><fmt:message key="jsp.dspace-admin.version-summary.text3"><fmt:param><%= itemID%></fmt:param></fmt:message></p> + + <%-- <td class="submitFormLabel">News:</td> --%> + <div class="form-group"> + <label for="summary"><fmt:message key="jsp.dspace-admin.version-summary.text"/></label> + <textarea class="form-control" name="summary" rows="10" cols="50"></textarea> + </div> + <%-- <input type="submit" name="submit_save" value="Save"> --%> + <input class="btn btn-success" type="submit" name="submit_version" value="<fmt:message key="jsp.version.version-summary.submit_version"/>" /> + <%-- <input type="submit" name="cancel" value="Cancel"> --%> + <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/tools/version-update-summary.jsp b/dspace-jspui/src/main/webapp/tools/version-update-summary.jsp new file mode 100644 index 0000000000000000000000000000000000000000..96aff6ddb93005dbaf945417e9f8d1f953f5820c --- /dev/null +++ b/dspace-jspui/src/main/webapp/tools/version-update-summary.jsp @@ -0,0 +1,53 @@ +<%-- + + 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/ + +--%> +<%-- + - Insert summary for versionable item JSP + - + - Attributes: + --%> + +<%@page import="org.dspace.core.Context"%> +<%@page import="org.dspace.app.webui.util.UIUtil"%> +<%@page import="org.dspace.app.webui.util.VersionUtil"%> +<%@ page contentType="text/html;charset=UTF-8" %> + +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" + prefix="fmt" %> + +<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> + + +<% + Integer itemID = (Integer)request.getAttribute("itemID"); + String versionID = (String)request.getAttribute("versionID"); + + Context context = UIUtil.obtainContext(request); + + request.setAttribute("LanguageSwitch", "hide"); +%> + +<dspace:layout style="submission" titlekey="jsp.dspace-admin.version-summary.title"> + <h1><fmt:message key="jsp.dspace-admin.version-summary.heading"/></h1> + + <form action="<%= request.getContextPath() %>/tools/history" method="post"> + <input type="hidden" name="itemID" value="<%= itemID %>" /> + <input type="hidden" name="versionID" value="<%= versionID %>" /> + <p><fmt:message key="jsp.dspace-admin.version-summary.text3"><fmt:param><%= itemID%></fmt:param></fmt:message></p> + <%-- <td class="submitFormLabel">News:</td> --%> + <div class="form-group"> + <label for="summary"><fmt:message key="jsp.dspace-admin.version-summary.text"/></label> + <textarea class="form-control" name="summary" rows="10" cols="50"><%= VersionUtil.getSummary(context, versionID) %></textarea> + </div> + <%-- <input type="submit" name="submit_save" value="Save"> --%> + <input class="btn btn-success" type="submit" name="submit_update" value="<fmt:message key="jsp.version.history.update"/>" /> + <%-- <input type="submit" name="cancel" value="Cancel"> --%> + <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/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-rest/README.md b/dspace-rest/README.md new file mode 100644 index 0000000000000000000000000000000000000000..404a986878f2fb71be96a4d739725682f8339e1f --- /dev/null +++ b/dspace-rest/README.md @@ -0,0 +1,75 @@ +#DSpace REST API (Jersey) + +A RESTful web services API for DSpace, built using JAX-RS1 JERSEY. + +##Getting Started +This REST API is integrated directly into the DSpace code-base. + + * Rebuild as normal: mvn + ant + * Deploy the webapp (i.e to tomcat) + * ```<Context path="/rest" docBase="/dspace/webapps/rest" allowLinking="true"/>``` + + +At this point, this is a READ ONLY API for DSpace, for the anonymous user. Only Anonymous READ Communities, Collections, Items, and Bitstreams are available. + +##Endpoints + +| Resource |CREATE|READ list|READ single|Edit|Delete|Search| +| ------------- |------|:-------:|-----------|----|------|------| +| /communities | | Y | Y | | | | +| /collections | | Y | Y | | | | +| /items | | | Y | | | | +| /bitstreams | | | Y | | | || + + +###Communities +View the list of top-level communities +- http://localhost:8080/rest/communities + +View a specific community +- http://localhost:8080/rest/communities/:ID + +View a specific community, list its subcommunities, and subcollections +- http://localhost:8080/rest/communities/:ID?expand=all + +###Collections +View the list of collections +- http://localhost:8080/rest/collections + +View a specific collection +- http://localhost:8080/rest/collections/:ID + +View a specific collection, and its items +- http://localhost:8080/rest/collections/:ID?expand=all + +###Items +View an Item, and see its bitstreams +- http://localhost:8080/rest/items/:ID + +###Bitstreams +View information about a bitstream +- http://localhost:8080/rest/bitstreams/:ID + +View/Download a specific Bitstream +- http://localhost:8080/rest/bitstreams/:ID/retrieve + +####Statistics +Recording of statistics for view of items or download of bitstreams (set stats = true in rest.cfg to enable stats recording) +http://localhost:8080/rest/items/:ID?userIP=ip&userAgent=userAgent&xforwarderfor=xforwarderfor +If no parameters are given the details of httprequest sender are used in statistics. +This enables tools to record the details of their user rather then themselves. + + +###Handles +Lookup a DSpaceObject by its Handle, this produces the name/ID, that you lookup in /bitstreams, /items, /collections, /communities +- http://localhost:8080/rest/handle/{prefix}/{suffix} + +##Expand +There is an ?expand= query parameter for more expensive operations. You can tack it on the end of endpoints. +It is optional, all, some or none. The response will usually indicate what the available "expand" options are. + +##HTTP Responses +* 200 OK - We have the requested object/objects +* 401 Unauthorized - The anonymous user does not have READ access to that object +* 404 Not Found - That object doesn't exist +* 500 Server Error - Likely a SQLException, IOException, more details in the logs. \ No newline at end of file diff --git a/dspace-rest/pom.xml b/dspace-rest/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..b08f62cfc245ebdaee6f0bfbe459d19422c70d6a --- /dev/null +++ b/dspace-rest/pom.xml @@ -0,0 +1,129 @@ +<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-rest</artifactId> + <packaging>war</packaging> + <version>4.1</version> + <name>DSpace RESTful web services API</name> + <url>http://demo.dspace.org</url> + + <parent> + <groupId>org.dspace</groupId> + <artifactId>dspace-parent</artifactId> + <version>4.1</version> + <relativePath>..</relativePath> + </parent> + + <properties> + <!-- This is the path to the root [dspace-src] directory. --> + <root.basedir>${basedir}/..</root.basedir> + </properties> + + <dependencies> + <!-- Jersey, for RESTful web services --> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-server</artifactId> + <version>1.17.1</version> + </dependency> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-servlet</artifactId> + <version>1.17.1</version> + </dependency> + <!-- JSON serialization, should I use jackson?--> + <dependency> + <groupId>com.sun.jersey</groupId> + <artifactId>jersey-json</artifactId> + <version>1.17.1</version> + </dependency> + + + + <!-- Spring 3 dependencies --> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </dependency> + + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + </dependency> + + + <!-- Jersey + Spring --> + <dependency> + <groupId>com.sun.jersey.contribs</groupId> + <artifactId>jersey-spring</artifactId> + <version>1.8</version> + <exclusions> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-core</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-beans</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + </exclusion> + <exclusion> + <groupId>org.springframework</groupId> + <artifactId>spring-aop</artifactId> + </exclusion> + </exclusions> + </dependency> + + + <!-- Use DSpace, for now, an older version to minimize spring generated dependency on Discovery --> + <dependency> + <groupId>org.dspace</groupId> + <artifactId>dspace-api</artifactId> + </dependency> + + <!-- Connecting to DSpace datasource sets a dependency on Postgres DB--> + <dependency> + <groupId>commons-dbcp</groupId> + <artifactId>commons-dbcp</artifactId> + </dependency> + <dependency> + <groupId>postgresql</groupId> + <artifactId>postgresql</artifactId> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.atteo</groupId> + <artifactId>evo-inflector</artifactId> + <version>1.0.1</version> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </dependency> + <dependency> + <groupId>org.dspace</groupId> + <artifactId>dspace-services</artifactId> + </dependency> + </dependencies> +</project> diff --git a/dspace-rest/src/main/java/org/dspace/rest/BitstreamResource.java b/dspace-rest/src/main/java/org/dspace/rest/BitstreamResource.java new file mode 100644 index 0000000000000000000000000000000000000000..34e2c413353ebad57bd59ab7653899c7d1f82fec --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/BitstreamResource.java @@ -0,0 +1,140 @@ +/** + * 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.rest; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.rest.common.Bitstream; +import org.dspace.usage.UsageEvent; +import org.dspace.utils.DSpace; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.sql.SQLException; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 10/2/13 + * Time: 5:56 PM + * To change this template use File | Settings | File Templates. + */ +@Path("/bitstreams") +public class BitstreamResource { + Logger log = Logger.getLogger(BitstreamResource.class); + private static org.dspace.core.Context context; + + private static final boolean writeStatistics; + + static{ + writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false); + } + + //BitstreamList - Not Implemented + + @GET + @Path("/{bitstream_id}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public Bitstream getBitstream(@PathParam("bitstream_id") Integer bitstream_id, @QueryParam("expand") String expand) { + try { + if(context == null || !context.isValid()) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id); + + if(AuthorizeManager.authorizeActionBoolean(context, bitstream, org.dspace.core.Constants.READ)) { + return new org.dspace.rest.common.Bitstream(bitstream, expand); + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + } catch(SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @GET + @Path("/{bitstream_id}/retrieve") + public javax.ws.rs.core.Response getFile(@PathParam("bitstream_id") final Integer bitstream_id, + @QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor, + @Context HttpHeaders headers, @Context HttpServletRequest request) { + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Bitstream bitstream = org.dspace.content.Bitstream.find(context, bitstream_id); + if(AuthorizeManager.authorizeActionBoolean(context, bitstream, org.dspace.core.Constants.READ)) { + if(writeStatistics){ + writeStats(bitstream_id, user_ip, user_agent, xforwarderfor, headers, request); + } + + return Response.ok(bitstream.retrieve()).type(bitstream.getFormat().getMIMEType()).build(); + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + + } catch (IOException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } catch (AuthorizeException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + } + + private void writeStats(Integer bitstream_id, String user_ip, String user_agent, + String xforwarderfor, HttpHeaders headers, + HttpServletRequest request) { + + try{ + DSpaceObject bitstream = DSpaceObject.find(context, Constants.BITSTREAM, bitstream_id); + + if(user_ip==null || user_ip.length()==0){ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + request, + context, + bitstream)); + } else{ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + user_ip, + user_agent, + xforwarderfor, + context, + bitstream)); + } + log.debug("fired event"); + + } catch(SQLException ex){ + log.error("SQL exception can't write usageEvent \n" + ex); + } + + } + +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java b/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java new file mode 100644 index 0000000000000000000000000000000000000000..476f505d96ae3eee9f4de9aa37d57a811afa9812 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/CollectionsResource.java @@ -0,0 +1,178 @@ +/** + * 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.rest; + + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.rest.common.Collection; +import org.dspace.usage.UsageEvent; +import org.dspace.utils.DSpace; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletContext; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import java.sql.SQLException; +import java.util.ArrayList; + +/* +The "Path" annotation indicates the URI this class will be available at relative to your base URL. For +example, if this web-app is launched at localhost using a context of "hello" and no URL pattern is defined +in the web.xml servlet mapping section, then the web service will be available at: + +http://localhost:8080/<webapp>/collections + */ +@Path("/collections") +public class CollectionsResource { + private static Logger log = Logger.getLogger(CollectionsResource.class); + + + @javax.ws.rs.core.Context ServletContext servletContext; + + private static org.dspace.core.Context context; + + private static final boolean writeStatistics; + + static{ + writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false); + } + + /* + The "GET" annotation indicates this method will respond to HTTP Get requests. + The "Produces" annotation indicates the MIME response the method will return. + */ + @GET + @Path("/") + @Produces(MediaType.TEXT_HTML) + public String listHTML() { + StringBuilder everything = new StringBuilder(); + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Collection[] collections = org.dspace.content.Collection.findAll(context); + for(org.dspace.content.Collection collection : collections) { + //TODO check auth... + everything.append("<li><a href='" + servletContext.getContextPath() + "/collections/" + collection.getID() + "'>" + collection.getID() + " - " + collection.getName() + "</a></li>\n"); + } + + return "<html><title>Hello!</title><body>Collections<br/><ul>" + everything.toString() + "</ul>.</body></html> "; + + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @GET + @Path("/") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.Collection[] list(@QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset) { + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Collection[] collections; + + //Only support paging if limit/offset are 0 or positive values. + if(limit != null && limit >= 0 && offset != null && offset >= 0) { + collections = org.dspace.content.Collection.findAll(context, limit, offset); + } else { + collections = org.dspace.content.Collection.findAll(context); + } + + ArrayList<org.dspace.rest.common.Collection> collectionArrayList = new ArrayList<org.dspace.rest.common.Collection>(); + for(org.dspace.content.Collection collection : collections) { + if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) { + org.dspace.rest.common.Collection restCollection = new org.dspace.rest.common.Collection(collection, null, context, limit, offset); + collectionArrayList.add(restCollection); + } // Not showing restricted-access collections + } + + return collectionArrayList.toArray(new org.dspace.rest.common.Collection[0]); + + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + @GET + @Path("/{collection_id}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.Collection getCollection(@PathParam("collection_id") Integer collection_id, @QueryParam("expand") String expand, + @QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset, + @QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor, + @Context HttpHeaders headers, @Context HttpServletRequest request) { + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Collection collection = org.dspace.content.Collection.find(context, collection_id); + if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) { + if(writeStatistics){ + writeStats(collection_id, user_ip, user_agent, xforwarderfor, headers, request); + } + return new org.dspace.rest.common.Collection(collection, expand, context, limit, offset); + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + private void writeStats(Integer collection_id, String user_ip, String user_agent, + String xforwarderfor, HttpHeaders headers, + HttpServletRequest request) { + + try{ + DSpaceObject collection = DSpaceObject.find(context, Constants.COLLECTION, collection_id); + + if(user_ip==null || user_ip.length()==0){ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + request, + context, + collection)); + } else{ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + user_ip, + user_agent, + xforwarderfor, + context, + collection)); + } + log.debug("fired event"); + + } catch(SQLException ex){ + log.error("SQL exception can't write usageEvent \n" + ex); + } + + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java b/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java new file mode 100644 index 0000000000000000000000000000000000000000..3be038972de9950ad5d3e2dfec1a5cf8b6e4f802 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/CommunitiesResource.java @@ -0,0 +1,163 @@ +/** + * 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.rest; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.usage.UsageEvent; +import org.dspace.utils.DSpace; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletContext; +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import java.sql.SQLException; +import java.util.ArrayList; + +/* +The "Path" annotation indicates the URI this class will be available at relative to your base URL. For +example, if this web-app is launched at localhost using a context of "hello" and no URL pattern is defined +in the web.xml servlet mapping section, then the web service will be available at: + +http://localhost:8080/<webapp>/communities + */ +@Path("/communities") +public class CommunitiesResource { + private static Logger log = Logger.getLogger(CommunitiesResource.class); + + private static org.dspace.core.Context context; + + private static final boolean writeStatistics; + + static{ + writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false); + } + + /* + The "GET" annotation indicates this method will respond to HTTP Get requests. + The "Produces" annotation indicates the MIME response the method will return. + */ + @GET + @Produces(MediaType.TEXT_HTML) + public String list() { + StringBuilder everything = new StringBuilder(); + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + org.dspace.content.Community[] communities = org.dspace.content.Community.findAllTop(context); + for(org.dspace.content.Community community : communities) { + everything.append(community.getName() + "<br/>\n"); + } + return "<html><title>Hello!</title><body>Communities:<br/>" + everything.toString() + ".</body></html> "; + + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + //TODO Respond to html for communities/:id + + @GET + @Path("/") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.Community[] list(@QueryParam("expand") String expand) { + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Community[] topCommunities = org.dspace.content.Community.findAllTop(context); + ArrayList<org.dspace.rest.common.Community> communityArrayList = new ArrayList<org.dspace.rest.common.Community>(); + for(org.dspace.content.Community community : topCommunities) { + if(AuthorizeManager.authorizeActionBoolean(context, community, org.dspace.core.Constants.READ)) { + //Only list communities that this user has access to. + org.dspace.rest.common.Community restCommunity = new org.dspace.rest.common.Community(community, expand, context); + communityArrayList.add(restCommunity); + } + } + + return communityArrayList.toArray(new org.dspace.rest.common.Community[0]); + + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } //finally? + } + + @GET + @Path("/{community_id}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.Community getCommunity(@PathParam("community_id") Integer community_id, @QueryParam("expand") String expand, + @QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor, + @Context HttpHeaders headers, @Context HttpServletRequest request) { + try { + if(context == null || !context.isValid() ) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Community community = org.dspace.content.Community.find(context, community_id); + if(AuthorizeManager.authorizeActionBoolean(context, community, org.dspace.core.Constants.READ)) { + if(writeStatistics){ + writeStats(community_id, user_ip, user_agent, xforwarderfor, headers, request); + } + return new org.dspace.rest.common.Community(community, expand, context); + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } //finally? + } + + private void writeStats(Integer community_id, String user_ip, String user_agent, + String xforwarderfor, HttpHeaders headers, + HttpServletRequest request) { + + try{ + DSpaceObject community = DSpaceObject.find(context, Constants.COMMUNITY, community_id); + + if(user_ip==null || user_ip.length()==0){ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + request, + context, + community)); + } else{ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + user_ip, + user_agent, + xforwarderfor, + context, + community)); + } + log.debug("fired event"); + + } catch(SQLException ex){ + log.error("SQL exception can't write usageEvent \n" + ex); + } + + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/HandleResource.java b/dspace-rest/src/main/java/org/dspace/rest/HandleResource.java new file mode 100644 index 0000000000000000000000000000000000000000..25270f301fafa4569d23c1dcc05bd54292d97e44 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/HandleResource.java @@ -0,0 +1,73 @@ +/** + * 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.rest; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; +import org.dspace.rest.common.Collection; +import org.dspace.rest.common.Community; +import org.dspace.rest.common.DSpaceObject; +import org.dspace.rest.common.Item; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.sql.SQLException; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 10/7/13 + * Time: 1:54 PM + * To change this template use File | Settings | File Templates. + */ +@Path("/handle") +public class HandleResource { + private static Logger log = Logger.getLogger(HandleResource.class); + private static org.dspace.core.Context context; + + @GET + @Path("/{prefix}/{suffix}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.DSpaceObject getObject(@PathParam("prefix") String prefix, @PathParam("suffix") String suffix, @QueryParam("expand") String expand) { + try { + if(context == null || !context.isValid() ) { + context = new Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.DSpaceObject dso = HandleManager.resolveToObject(context, prefix + "/" + suffix); + if(dso == null) { + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + log.info("DSO Lookup by handle: [" + prefix + "] / [" + suffix + "] got result of: " + dso.getTypeText() + "_" + dso.getID()); + + if(AuthorizeManager.authorizeActionBoolean(context, dso, org.dspace.core.Constants.READ)) { + switch(dso.getType()) { + case Constants.COMMUNITY: + return new Community((org.dspace.content.Community) dso, expand, context); + case Constants.COLLECTION: + return new Collection((org.dspace.content.Collection) dso, expand, context, null, null); + case Constants.ITEM: + return new Item((org.dspace.content.Item) dso, expand, context); + default: + return new DSpaceObject(dso); + } + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/ItemsResource.java b/dspace-rest/src/main/java/org/dspace/rest/ItemsResource.java new file mode 100644 index 0000000000000000000000000000000000000000..cffd04dbd6ae1b3867dcb7a7b04748e4990da151 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/ItemsResource.java @@ -0,0 +1,114 @@ +/** + * 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.rest; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import javax.servlet.http.HttpServletRequest; + +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.sql.SQLException; + +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.usage.UsageEvent; +import org.dspace.utils.DSpace; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 9/19/13 + * Time: 4:54 PM + * To change this template use File | Settings | File Templates. + */ +@Path("/items") +public class ItemsResource { + + private static final boolean writeStatistics; + + static{ + writeStatistics=ConfigurationManager.getBooleanProperty("rest","stats",false); + } + + /** log4j category */ + private static final Logger log = Logger.getLogger(ItemsResource.class); + //ItemList - Not Implemented + + private static org.dspace.core.Context context; + + @GET + @Path("/{item_id}") + @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) + public org.dspace.rest.common.Item getItem(@PathParam("item_id") Integer item_id, @QueryParam("expand") String expand, + @QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor, + @Context HttpHeaders headers, @Context HttpServletRequest request) throws WebApplicationException { + + + try { + if(context == null || !context.isValid()) { + context = new org.dspace.core.Context(); + //Failed SQL is ignored as a failed SQL statement, prevent: current transaction is aborted, commands ignored until end of transaction block + context.getDBConnection().setAutoCommit(true); + } + + org.dspace.content.Item item = org.dspace.content.Item.find(context, item_id); + + if(AuthorizeManager.authorizeActionBoolean(context, item, org.dspace.core.Constants.READ)) { + if(writeStatistics){ + writeStats(item_id, user_ip, user_agent, xforwarderfor, headers, request); + } + return new org.dspace.rest.common.Item(item, expand, context); + } else { + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + + } catch (SQLException e) { + log.error(e.getMessage()); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + + private void writeStats(Integer item_id, String user_ip, String user_agent, + String xforwarderfor, HttpHeaders headers, + HttpServletRequest request) { + + try{ + DSpaceObject item = DSpaceObject.find(context, Constants.ITEM, item_id); + + if(user_ip==null || user_ip.length()==0){ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + request, + context, + item)); + } else{ + new DSpace().getEventService().fireEvent( + new UsageEvent( + UsageEvent.Action.VIEW, + user_ip, + user_agent, + xforwarderfor, + context, + item)); + } + log.debug("fired event"); + + } catch(SQLException ex){ + log.error("SQL exception can't write usageEvent \n" + ex); + } + + } + +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/RestIndex.java b/dspace-rest/src/main/java/org/dspace/rest/RestIndex.java new file mode 100644 index 0000000000000000000000000000000000000000..3c0188f6767d05921d1c24d88724b2504c235851 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/RestIndex.java @@ -0,0 +1,45 @@ +/** + * 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.rest; + +import javax.servlet.ServletContext; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +/* +Root of API, should have documentation on where to find the other resources. + */ +@Path("/") +public class RestIndex { + @javax.ws.rs.core.Context public static ServletContext servletContext; + + /* + The "GET" annotation indicates this method will respond to HTTP Get requests. + The "Produces" annotation indicates the MIME response the method will return. + */ + @GET + @Produces(MediaType.TEXT_HTML) + public String sayHtmlHello() { + return "<html><title>DSpace REST</title>" + + "<body><h1>DSpace REST API</h1>" + + "<ul>" + + "<li><a href='" + servletContext.getContextPath() + "/communities'>/communities</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/communities/1'>/communities/1</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/collections'>/collections</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/collections/1'>/collections/1</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/items'>/items</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/items/1'>/items/1</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/bitstreams'>/bitstreams</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/bitstreams/1'>/bitstreams/1</a></li>" + + "<li><a href='" + servletContext.getContextPath() + "/bitstreams/1/retrieve'>/bitstreams/1/retrieve</a></li>" + + "</ul>" + + "</body></html> "; + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/Bitstream.java b/dspace-rest/src/main/java/org/dspace/rest/common/Bitstream.java new file mode 100644 index 0000000000000000000000000000000000000000..ffe28af1c02998fd9987fb9edef6c8802588f51b --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/Bitstream.java @@ -0,0 +1,156 @@ +/** + * 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.rest.common; + +import org.apache.log4j.Logger; +import org.dspace.core.Constants; + +import javax.xml.bind.annotation.XmlRootElement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 9/21/13 + * Time: 12:54 AM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "bitstream") +public class Bitstream extends DSpaceObject { + Logger log = Logger.getLogger(Bitstream.class); + + private String bundleName; + private String description; + private String format; + private String mimeType; + private Long sizeBytes; + private DSpaceObject parentObject; + private String retrieveLink; + private CheckSum checkSum; + private Integer sequenceId; + + public Bitstream() { + + } + + public Bitstream(org.dspace.content.Bitstream bitstream, String expand) throws SQLException{ + super(bitstream); + setup(bitstream, expand); + } + + public void setup(org.dspace.content.Bitstream bitstream, String expand) throws SQLException{ + List<String> expandFields = new ArrayList<String>(); + if(expand != null) { + expandFields = Arrays.asList(expand.split(",")); + } + + //A logo bitstream might not have a bundle... + if(bitstream.getBundles() != null & bitstream.getBundles().length >= 0) { + if(bitstream.getParentObject().getType() == Constants.ITEM) { + bundleName = bitstream.getBundles()[0].getName(); + } + } + + description = bitstream.getDescription(); + format = bitstream.getFormatDescription(); + sizeBytes = bitstream.getSize(); + retrieveLink = "/bitstreams/" + bitstream.getID() + "/retrieve"; + mimeType = bitstream.getFormat().getMIMEType(); + sequenceId = bitstream.getSequenceID(); + CheckSum checkSum = new CheckSum(); + checkSum.setCheckSumAlgorith(bitstream.getChecksumAlgorithm()); + checkSum.setValue(bitstream.getChecksum()); + this.setCheckSum(checkSum); + + if(expandFields.contains("parent") || expandFields.contains("all")) { + parentObject = new DSpaceObject(bitstream.getParentObject()); + } else { + this.addExpand("parent"); + } + + if(!expandFields.contains("all")) { + this.addExpand("all"); + } + } + + public Integer getSequenceId() { + return sequenceId; + } + + public void setSequenceId(Integer sequenceId) { + this.sequenceId = sequenceId; + } + + public String getBundleName() { + return bundleName; + } + + public void setBundleName(String bundleName) { + this.bundleName = bundleName; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setFormat(String format) { + this.format = format; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public void setSizeBytes(Long sizeBytes) { + this.sizeBytes = sizeBytes; + } + + public void setParentObject(DSpaceObject parentObject) { + this.parentObject = parentObject; + } + + public void setRetrieveLink(String retrieveLink) { + this.retrieveLink = retrieveLink; + } + + public String getDescription() { + return description; + } + + public String getFormat() { + return format; + } + + public String getMimeType() { + return mimeType; + } + + public Long getSizeBytes() { + return sizeBytes; + } + + public String getRetrieveLink() { + return retrieveLink; + } + + public DSpaceObject getParentObject() { + return parentObject; + } + + public CheckSum getCheckSum() { + return checkSum; + } + + public void setCheckSum(CheckSum checkSum) { + this.checkSum = checkSum; + } + +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/CheckSum.java b/dspace-rest/src/main/java/org/dspace/rest/common/CheckSum.java new file mode 100644 index 0000000000000000000000000000000000000000..2c716f6b9db9d8bc2c3b10f570c7927dfc4e1e72 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/CheckSum.java @@ -0,0 +1,39 @@ +/** + * 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.rest.common; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; +import javax.xml.bind.annotation.XmlValue; + +@XmlType +public class CheckSum{ + String checkSumAlgorithm; + String value; + + public CheckSum(){} + + @XmlAttribute(name="checkSumAlgorithm") + public String getCheckSumAlgorith() { + return checkSumAlgorithm; + } + + public void setCheckSumAlgorith(String checkSumAlgorith) { + this.checkSumAlgorithm = checkSumAlgorith; + } + + @XmlValue + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} \ No newline at end of file diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java b/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java new file mode 100644 index 0000000000000000000000000000000000000000..b8e32ab91d9a05920c99daff23070d1c3242a285 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/Collection.java @@ -0,0 +1,203 @@ +/** + * 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.rest.common; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.ItemIterator; +import org.dspace.core.Context; + +import javax.ws.rs.WebApplicationException; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 5/22/13 + * Time: 9:41 AM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "collection") +public class Collection extends DSpaceObject { + Logger log = Logger.getLogger(Collection.class); + + //Relationships + private Bitstream logo; + private Community parentCommunity; + private List<Community> parentCommunityList = new ArrayList<Community>(); + + private List<Item> items = new ArrayList<Item>(); + + //Collection-Metadata + private String license; + private String copyrightText, introductoryText, shortDescription, sidebarText; + + //Calculated + private Integer numberItems; + + public Collection(){} + + public Collection(org.dspace.content.Collection collection, String expand, Context context, Integer limit, Integer offset) throws SQLException, WebApplicationException{ + super(collection); + setup(collection, expand, context, limit, offset); + } + + private void setup(org.dspace.content.Collection collection, String expand, Context context, Integer limit, Integer offset) throws SQLException{ + List<String> expandFields = new ArrayList<String>(); + if(expand != null) { + expandFields = Arrays.asList(expand.split(",")); + } + + this.setCopyrightText(collection.getMetadata(org.dspace.content.Collection.COPYRIGHT_TEXT)); + this.setIntroductoryText(collection.getMetadata(org.dspace.content.Collection.INTRODUCTORY_TEXT)); + this.setShortDescription(collection.getMetadata(org.dspace.content.Collection.SHORT_DESCRIPTION)); + this.setSidebarText(collection.getMetadata(org.dspace.content.Collection.SIDEBAR_TEXT)); + + if(expandFields.contains("parentCommunityList") || expandFields.contains("all")) { + org.dspace.content.Community[] parentCommunities = collection.getCommunities(); + for(org.dspace.content.Community parentCommunity : parentCommunities) { + this.addParentCommunityList(new Community(parentCommunity, null, context)); + } + } else { + this.addExpand("parentCommunityList"); + } + + if(expandFields.contains("parentCommunity") | expandFields.contains("all")) { + org.dspace.content.Community parentCommunity = (org.dspace.content.Community) collection.getParentObject(); + this.setParentCommunity(new Community(parentCommunity, null, context)); + } else { + this.addExpand("parentCommunity"); + } + + //TODO: Item paging. limit, offset/page + if(expandFields.contains("items") || expandFields.contains("all")) { + ItemIterator childItems; + if(limit != null && limit >= 0 && offset != null && offset >= 0) { + childItems = collection.getItems(limit, offset); + } else { + childItems = collection.getItems(); + } + + items = new ArrayList<Item>(); + while(childItems.hasNext()) { + org.dspace.content.Item item = childItems.next(); + if(AuthorizeManager.authorizeActionBoolean(context, item, org.dspace.core.Constants.READ)) { + items.add(new Item(item, null, context)); + } + } + } else { + this.addExpand("items"); + } + + if(expandFields.contains("license") || expandFields.contains("all")) { + setLicense(collection.getLicense()); + } else { + this.addExpand("license"); + } + + if(expandFields.contains("logo") || expandFields.contains("all")) { + if(collection.getLogo() != null) { + this.logo = new Bitstream(collection.getLogo(), null); + } + } + else { + this.addExpand("logo"); + } + + if(!expandFields.contains("all")) { + this.addExpand("all"); + } + + this.setNumberItems(collection.countItems()); + } + + public Bitstream getLogo() { + return logo; + } + + public Integer getNumberItems() { + return numberItems; + } + + public void setNumberItems(Integer numberItems) { + this.numberItems = numberItems; + } + + public Community getParentCommunity() { + return parentCommunity; + } + + public void setParentCommunity(Community parentCommunity) { + this.parentCommunity = parentCommunity; + } + + public List<Item> getItems() { + return items; + } + + public void setItems(List<Item> items) { + this.items = items; + } + + public void setParentCommunityList(List<Community> parentCommunityList) { + this.parentCommunityList = parentCommunityList; + } + + public List<Community> getParentCommunityList() { + return parentCommunityList; + } + + public void addParentCommunityList(Community parentCommunity) { + this.parentCommunityList.add(parentCommunity); + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public String getCopyrightText() { + return copyrightText; + } + + public void setCopyrightText(String copyrightText) { + this.copyrightText = copyrightText; + } + + public String getIntroductoryText() { + return introductoryText; + } + + public void setIntroductoryText(String introductoryText) { + this.introductoryText = introductoryText; + } + + public String getShortDescription() { + return shortDescription; + } + + public void setShortDescription(String shortDescription) { + this.shortDescription = shortDescription; + } + + public String getSidebarText() { + return sidebarText; + } + + public void setSidebarText(String sidebarText) { + this.sidebarText = sidebarText; + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/Community.java b/dspace-rest/src/main/java/org/dspace/rest/common/Community.java new file mode 100644 index 0000000000000000000000000000000000000000..1c135610078d3dae6f4f7346ccac5ae9c2568c3f --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/Community.java @@ -0,0 +1,174 @@ +/** + * 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.rest.common; + +import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.core.Context; + +import javax.ws.rs.WebApplicationException; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 5/22/13 + * Time: 9:41 AM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "community") +public class Community extends DSpaceObject{ + private static Logger log = Logger.getLogger(Community.class); + + //Exandable relationships + private Bitstream logo; + + private Community parentCommunity; + + private String copyrightText, introductoryText, shortDescription, sidebarText; + private Integer countItems; + + @XmlElement(name = "subcommunities", required = true) + private List<Community> subCommunities = new ArrayList<Community>(); + + private List<Collection> collections = new ArrayList<Collection>(); + + public Community(){} + + public Community(org.dspace.content.Community community, String expand, Context context) throws SQLException, WebApplicationException{ + super(community); + setup(community, expand, context); + } + + private void setup(org.dspace.content.Community community, String expand, Context context) throws SQLException{ + List<String> expandFields = new ArrayList<String>(); + if(expand != null) { + expandFields = Arrays.asList(expand.split(",")); + } + + this.setCopyrightText(community.getMetadata(org.dspace.content.Community.COPYRIGHT_TEXT)); + this.setIntroductoryText(community.getMetadata(org.dspace.content.Community.INTRODUCTORY_TEXT)); + this.setShortDescription(community.getMetadata(org.dspace.content.Community.SHORT_DESCRIPTION)); + this.setSidebarText(community.getMetadata(org.dspace.content.Community.SIDEBAR_TEXT)); + this.setCountItems(community.countItems()); + + if(expandFields.contains("parentCommunity") || expandFields.contains("all")) { + org.dspace.content.Community parentCommunity = community.getParentCommunity(); + if(parentCommunity != null) { + setParentCommunity(new Community(parentCommunity, null, context)); + } + } else { + this.addExpand("parentCommunity"); + } + + if(expandFields.contains("collections") || expandFields.contains("all")) { + org.dspace.content.Collection[] collectionArray = community.getCollections(); + collections = new ArrayList<Collection>(); + for(org.dspace.content.Collection collection : collectionArray) { + if(AuthorizeManager.authorizeActionBoolean(context, collection, org.dspace.core.Constants.READ)) { + collections.add(new Collection(collection, null, context, null, null)); + } else { + log.info("Omitted restricted collection: " + collection.getID() + " _ " + collection.getName()); + } + } + } else { + this.addExpand("collections"); + } + + if(expandFields.contains("subCommunities") || expandFields.contains("all")) { + org.dspace.content.Community[] communityArray = community.getSubcommunities(); + subCommunities = new ArrayList<Community>(); + for(org.dspace.content.Community subCommunity : communityArray) { + if(AuthorizeManager.authorizeActionBoolean(context, subCommunity, org.dspace.core.Constants.READ)) { + subCommunities.add(new Community(subCommunity, null, context)); + } else { + log.info("Omitted restricted subCommunity: " + subCommunity.getID() + " _ " + subCommunity.getName()); + } + } + } else { + this.addExpand("subCommunities"); + } + + if(expandFields.contains("logo") || expandFields.contains("all")) { + if(community.getLogo() != null) { + logo = new Bitstream(community.getLogo(), null); + } + } else { + this.addExpand("logo"); + } + + if(!expandFields.contains("all")) { + this.addExpand("all"); + } + } + + public List<Collection> getCollections() { + return collections; + } + + public void setCollections(List<Collection> collections) { + this.collections = collections; + } + + public Integer getCountItems() { + return countItems; + } + + public void setCountItems(Integer countItems) { + this.countItems = countItems; + } + + public String getSidebarText() { + return sidebarText; + } + + public void setSidebarText(String sidebarText) { + this.sidebarText = sidebarText; + } + + public String getShortDescription() { + return shortDescription; + } + + public void setShortDescription(String shortDescription) { + this.shortDescription = shortDescription; + } + + public String getIntroductoryText() { + return introductoryText; + } + + public void setIntroductoryText(String introductoryText) { + this.introductoryText = introductoryText; + } + + public String getCopyrightText() { + return copyrightText; + } + + public void setCopyrightText(String copyrightText) { + this.copyrightText = copyrightText; + } + + public Community getParentCommunity() { + return parentCommunity; + } + + public void setParentCommunity(Community parentCommunity) { + this.parentCommunity = parentCommunity; + } + + public Bitstream getLogo() { + return logo; + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/DSpaceObject.java b/dspace-rest/src/main/java/org/dspace/rest/common/DSpaceObject.java new file mode 100644 index 0000000000000000000000000000000000000000..864872d606f280207e0a9256059b4dc5d01ea8d2 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/DSpaceObject.java @@ -0,0 +1,100 @@ +/** + * 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.rest.common; + +import org.atteo.evo.inflector.English; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 10/7/13 + * Time: 12:11 PM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "dspaceobject") +public class DSpaceObject { + private Integer id; + + private String name; + + private String handle; + + private String type; + + @XmlElement(name = "link", required = true) + private String link; + + @XmlElement(required = true) + private ArrayList<String> expand = new ArrayList<String>(); + + public DSpaceObject() { + + } + + public DSpaceObject(org.dspace.content.DSpaceObject dso) { + setID(dso.getID()); + setName(dso.getName()); + setHandle(dso.getHandle()); + setType(dso.getTypeText().toLowerCase()); + } + + public Integer getID() { + return id; + } + + public void setID(Integer id) { + this.id = id; + } + + public String getName(){ + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHandle() { + return handle; + } + + public void setHandle(String handle) { + this.handle = handle; + } + + public String getLink() { + //TODO, get actual contextPath of /rest/ + return "/rest/" + English.plural(getType()) + "/" + getID(); + } + + public String getType() { + return this.type; + } + + public void setType(String type) { + this.type = type; + } + + + public List<String> getExpand() { + return expand; + } + + public void setExpand(ArrayList<String> expand) { + this.expand = expand; + } + + public void addExpand(String expandableAttribute) { + this.expand.add(expandableAttribute); + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/Item.java b/dspace-rest/src/main/java/org/dspace/rest/common/Item.java new file mode 100644 index 0000000000000000000000000000000000000000..d21ba75cc891c7a7887241d1b3de5273679a2512 --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/Item.java @@ -0,0 +1,189 @@ +/** + * 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.rest.common; + +import org.apache.log4j.Logger; +import org.dspace.app.util.MetadataExposure; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.Bundle; +import org.dspace.content.DCValue; +import org.dspace.core.Context; + +import javax.ws.rs.WebApplicationException; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 9/19/13 + * Time: 4:50 PM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "item") +public class Item extends DSpaceObject { + Logger log = Logger.getLogger(Item.class); + + String isArchived; + String isWithdrawn; + String lastModified; + + Collection parentCollection; + List<Collection> parentCollectionList; + + List<Community> parentCommunityList; + + List<MetadataEntry> metadata; + + List<Bitstream> bitstreams; + + public Item(){} + + public Item(org.dspace.content.Item item, String expand, Context context) throws SQLException, WebApplicationException{ + super(item); + setup(item, expand, context); + } + + private void setup(org.dspace.content.Item item, String expand, Context context) throws SQLException{ + List<String> expandFields = new ArrayList<String>(); + if(expand != null) { + expandFields = Arrays.asList(expand.split(",")); + } + + if(expandFields.contains("metadata") || expandFields.contains("all")) { + metadata = new ArrayList<MetadataEntry>(); + DCValue[] dcvs = item.getMetadata(org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY, org.dspace.content.Item.ANY); + for (DCValue dcv : dcvs) { + if (!MetadataExposure.isHidden(context, dcv.schema, dcv.element, dcv.qualifier)) { + metadata.add(new MetadataEntry(dcv.getField(), dcv.value)); + } + } + } else { + this.addExpand("metadata"); + } + + this.setArchived(Boolean.toString(item.isArchived())); + this.setWithdrawn(Boolean.toString(item.isWithdrawn())); + this.setLastModified(item.getLastModified().toString()); + + if(expandFields.contains("parentCollection") || expandFields.contains("all")) { + this.parentCollection = new Collection(item.getOwningCollection(), null, context, null, null); + } else { + this.addExpand("parentCollection"); + } + + if(expandFields.contains("parentCollectionList") || expandFields.contains("all")) { + this.parentCollectionList = new ArrayList<Collection>(); + org.dspace.content.Collection[] collections = item.getCollections(); + for(org.dspace.content.Collection collection : collections) { + this.parentCollectionList.add(new Collection(collection, null, context, null, null)); + } + } else { + this.addExpand("parentCollectionList"); + } + + if(expandFields.contains("parentCommunityList") || expandFields.contains("all")) { + this.parentCommunityList = new ArrayList<Community>(); + org.dspace.content.Community[] communities = item.getCommunities(); + for(org.dspace.content.Community community : communities) { + this.parentCommunityList.add(new Community(community, null, context)); + } + } else { + this.addExpand("parentCommunityList"); + } + + //TODO: paging - offset, limit + if(expandFields.contains("bitstreams") || expandFields.contains("all")) { + bitstreams = new ArrayList<Bitstream>(); + Bundle[] bundles = item.getBundles(); + for(Bundle bundle : bundles) { + org.dspace.content.Bitstream[] itemBitstreams = bundle.getBitstreams(); + for(org.dspace.content.Bitstream itemBitstream : itemBitstreams) { + if(AuthorizeManager.authorizeActionBoolean(context, itemBitstream, org.dspace.core.Constants.READ)) { + bitstreams.add(new Bitstream(itemBitstream, null)); + } + } + } + } else { + this.addExpand("bitstreams"); + } + + if(!expandFields.contains("all")) { + this.addExpand("all"); + } + } + + public String getArchived() { + return isArchived; + } + + public void setArchived(String archived) { + isArchived = archived; + } + + public String getWithdrawn() { + return isWithdrawn; + } + + public void setWithdrawn(String withdrawn) { + isWithdrawn = withdrawn; + } + + public String getLastModified() { + return lastModified; + } + + public void setLastModified(String lastModified) { + this.lastModified = lastModified; + } + + public Collection getParentCollection() { + return parentCollection; + } + + public List<Collection> getParentCollectionList() { + return parentCollectionList; + } + + public List<MetadataEntry> getMetadata() { + return metadata; + } + + public List<Bitstream> getBitstreams() { + return bitstreams; + } + + public List<Community> getParentCommunityList() { + return parentCommunityList; + } + + public void setParentCollection(Collection parentCollection) { + this.parentCollection = parentCollection; + } + + public void setParentCollectionList(List<Collection> parentCollectionList) { + this.parentCollectionList = parentCollectionList; + } + + public void setParentCommunityList(List<Community> parentCommunityList) { + this.parentCommunityList = parentCommunityList; + } + + @XmlElement(required = true) + public void setMetadata(List<MetadataEntry> metadata) { + this.metadata = metadata; + } + + public void setBitstreams(List<Bitstream> bitstreams) { + this.bitstreams = bitstreams; + } +} diff --git a/dspace-rest/src/main/java/org/dspace/rest/common/MetadataEntry.java b/dspace-rest/src/main/java/org/dspace/rest/common/MetadataEntry.java new file mode 100644 index 0000000000000000000000000000000000000000..18d28b0eabc525bd795e1c0a6b518fd336e7503d --- /dev/null +++ b/dspace-rest/src/main/java/org/dspace/rest/common/MetadataEntry.java @@ -0,0 +1,46 @@ +/** + * 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.rest.common; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Created with IntelliJ IDEA. + * User: peterdietz + * Date: 9/20/13 + * Time: 5:51 PM + * To change this template use File | Settings | File Templates. + */ +@XmlRootElement(name = "metadataentry") +public class MetadataEntry { + String key; + String value; + + public MetadataEntry() {} + + public MetadataEntry(String key, String value) { + this.key = key; + this.value = value; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } +} diff --git a/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml b/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml new file mode 100644 index 0000000000000000000000000000000000000000..0d72338d12051c4f6dac2a7ce1ebf1cf1b7ba2ed --- /dev/null +++ b/dspace-rest/src/main/webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans + xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"> + + <!-- Acquires the DSpace Utility Class with initialized Service Manager --> + <bean id="dspace" class="org.dspace.utils.DSpace"/> + + <!-- Acquires reference to EventService --> + <bean id="dspace.eventService" factory-bean="dspace" factory-method="getEventService"/> + + <!-- Inject the Default LoggerUsageEventListener into the EventService --> + <bean class="org.dspace.usage.LoggerUsageEventListener"> + <property name="eventService" > + <ref bean="dspace.eventService"/> + </property> + </bean> + + <!-- Inject the Default LoggerUsageEventListener into the EventService --> + <bean class="org.dspace.statistics.SolrLoggerUsageEventListener"> + <property name="eventService" > + <ref bean="dspace.eventService"/> + </property> + </bean> + + <!-- Elastic Search --> + <!--<bean class="org.dspace.statistics.ElasticSearchLoggerEventListener"> + <property name="eventService"> + <ref bean="dspace.eventService" /> + </property> + </bean>--> + + <!-- + Uncomment to enable TabFileUsageEventListener + <bean class="org.dspace.app.statistics.TabFileUsageEventListener"> + <property name="eventService" > + <ref bean="dspace.eventService"/> + </property> + </bean> + --> + + <!-- + Uncomment to enable PassiveUsageEventListener + <bean class="org.dspace.app.statistics.PassiveUsageEventListener"> + <property name="eventService" > + <ref bean="dspace.eventService"/> + </property> + </bean> + --> + +</beans> diff --git a/dspace-rest/src/main/webapp/WEB-INF/web.xml b/dspace-rest/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..2167ea94ca5f43ca59504aba1a2b29773e68b7ea --- /dev/null +++ b/dspace-rest/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,103 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://java.sun.com/xml/ns/javaee" + xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" + id="WebApp_ID" version="2.5"> + <servlet> + <servlet-name>DSpace REST API</servlet-name> + <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> + <init-param> + <!-- + The jersey ServletContainer will look for our Root Resource Class + (i.e. our HelloWorld class) in the foo.bar package + There are other ways to register this; see the jersey documentation for + more details + --> + <param-name>com.sun.jersey.config.property.packages</param-name> + <param-value>org.dspace.rest</param-value> + </init-param> + <init-param> + <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> + <param-value>true</param-value> + </init-param> + <!-- + Load the ServletContainer at startup. A value of 1 indicates the ServletContainer + is a high priority servlet to load + --> + <load-on-startup>1</load-on-startup> + </servlet> + <servlet-mapping> + <servlet-name>DSpace REST API</servlet-name> + <!-- + The url-pattern can be used to define your URL. + Example, running local host with a context of "hello" and path annotation of "world" + on the HelloWorld class: + + <url-pattern>/*</url-pattern> + The web service will be available at: http://localhost:8080/hello/world + + + <url-pattern>/jersey/*</url-pattern> + The web service will be available at http://localhost:8080/hello/jersey/world + --> + <url-pattern>/*</url-pattern> + </servlet-mapping> + + <!-- DSpace Configuration Information --> + <context-param> + <param-name>dspace-config</param-name> + <param-value>${dspace.dir}/config/dspace.cfg</param-value> + </context-param> + + <!-- 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> + </context-param> + + <context-param> + <param-name>contextConfigLocation</param-name> + <param-value> + /WEB-INF/applicationContext.xml + </param-value> + <!-- + Add this context if using Spring Security + /WEB-INF/applicationContext-security.xml + --> + </context-param> + + <listener> + <listener-class>org.dspace.app.util.DSpaceContextListener</listener-class> + </listener> + + <!-- kernel start listener (from impl) + The following listener can be used instead of the filter below, it is simpler, cleaner + and eliminates the need for a DSpaceKernelServletFilter filter to be involved with the + request cycle. + --> + <listener> + <listener-class>org.dspace.servicemanager.servlet.DSpaceKernelServletContextListener</listener-class> + </listener> + + <listener> + <listener-class> + org.springframework.web.context.ContextLoaderListener + </listener-class> + </listener> + + + +</web-app> 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/EmailService.java b/dspace-services/src/main/java/org/dspace/services/EmailService.java new file mode 100644 index 0000000000000000000000000000000000000000..1b4a0d798be0158ccccd67a81e915732979adce6 --- /dev/null +++ b/dspace-services/src/main/java/org/dspace/services/EmailService.java @@ -0,0 +1,23 @@ +/** + * 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.services; + +import javax.mail.Session; + +/** + * + * @author mwood + */ +public interface EmailService +{ + /** + * Provide a reference to the JavaMail session. + */ + Session getSession(); +} 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/java/org/dspace/services/email/EmailServiceImpl.java b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..24a35462a886a7b95de889c1076b213f5e409501 --- /dev/null +++ b/dspace-services/src/main/java/org/dspace/services/email/EmailServiceImpl.java @@ -0,0 +1,138 @@ +/** + * 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.services.email; + +import java.util.Properties; +import javax.mail.Authenticator; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import org.dspace.kernel.mixins.InitializedService; +import org.dspace.services.ConfigurationService; +import org.dspace.services.EmailService; +import org.dspace.utils.DSpace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Required; + +/** + * Provides mail sending services through JavaMail. If a {@link javax.mail.Session} + * instance is provided through JNDI, it will be used. If not, then a session + * will be created from DSpace configuration data ({@code mail.server} etc.) + * + * @author mwood + */ +public class EmailServiceImpl + extends Authenticator + implements EmailService, InitializedService +{ + private static final Logger logger = (Logger) LoggerFactory.getLogger(EmailServiceImpl.class); + + private Session session = null; + + private ConfigurationService cfg = null; + + /** Inject the ConfigurationService */ + @Autowired + @Required + public void setCfg(ConfigurationService cfg) + { + this.cfg = cfg; + } + + /** + * Provide a reference to the JavaMail session. + * + * @return the managed Session, or null if none could be created. + */ + @Override + public Session getSession() + { + return session; + } + + @Override + public void init() + { + // See if there is already a Session in our environment + String sessionName = cfg.getProperty("mail.session.name"); + if (null == sessionName) + { + sessionName = "Session"; + } + try + { + InitialContext ctx = new InitialContext(null); + session = (Session) ctx.lookup("java:comp/env/mail/" + sessionName); + } catch (NamingException ex) + { + logger.warn("Couldn't get an email session from environment: {}", + ex.getMessage()); + } + + if (null != session) + { + logger.info("Email session retrieved from environment."); + } + else + { // No Session provided, so create one + logger.info("Initializing an email session from configuration."); + Properties props = new Properties(); + props.put("mail.transport.protocol", "smtp"); + String host = cfg.getProperty("mail.server"); + if (null != host) + { + props.put("mail.host", cfg.getProperty("mail.server")); + } + String port = cfg.getProperty("mail.server.port"); + if (null != port) + { + props.put("mail.smtp.port", port); + } + + if (null == cfg.getProperty("mail.server.username")) + { + session = Session.getInstance(props); + } + else + { + props.put("mail.smtp.auth", "true"); + session = Session.getInstance(props, this); + } + + // Set extra configuration properties + String extras = cfg.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); + } + } + } + } + + @Override + protected PasswordAuthentication getPasswordAuthentication() + { + if (null == cfg) + { + cfg = new DSpace().getConfigurationService(); + } + + return new PasswordAuthentication( + cfg.getProperty("mail.server.username"), + cfg.getProperty("mail.server.password")); + } +} diff --git a/dspace-services/src/main/java/org/dspace/services/email/package-info.java b/dspace-services/src/main/java/org/dspace/services/email/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..38154caeecaa6cd3f40c53d7277918d107805dfa --- /dev/null +++ b/dspace-services/src/main/java/org/dspace/services/email/package-info.java @@ -0,0 +1,13 @@ +/** + * 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/ + */ + +/** + * Manages a JavaMail session for code which wants to send email. + */ + +package org.dspace.services.email; 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-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java b/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..377734ddf4c807b9455ed827d994b5d4bf110901 --- /dev/null +++ b/dspace-services/src/test/java/org/dspace/services/email/EmailServiceImplTest.java @@ -0,0 +1,102 @@ +/** + * 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.services.email; + +import javax.mail.MessagingException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import org.dspace.services.ConfigurationService; +import org.dspace.services.EmailService; +import org.dspace.test.DSpaceAbstractKernelTest; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import org.junit.Test; + +/** + * + * @author mwood + */ +public class EmailServiceImplTest + extends DSpaceAbstractKernelTest +{ + private static final String USERNAME = "auser"; + private static final String PASSWORD = "apassword"; + + /* + @BeforeClass + public static void setUpClass() + throws Exception + { + } + + @AfterClass + public static void tearDownClass() + throws Exception + { + } + + @Before + public void setUp() + { + } + + @After + public void tearDown() + { + } + */ + + /** + * Test of getSession method, of class EmailService. + */ + @Test + public void testGetSession() + throws MessagingException + { + System.out.println("getSession"); + Session session; + EmailService instance = getService(EmailServiceImpl.class); + + // Try to get a Session + session = instance.getSession(); + assertNotNull(" getSession returned null", session); + } + + private static final String CFG_USERNAME = "mail.server.username"; + private static final String CFG_PASSWORD = "mail.server.password"; + + /** + * Test of getPasswordAuthentication method, of class EmailServiceImpl. + */ + @Test + public void testGetPasswordAuthentication() + { + System.out.println("getPasswordAuthentication"); + ConfigurationService cfg = getKernel().getConfigurationService(); + + // Save existing values. + String oldUsername = cfg.getProperty(CFG_USERNAME); + String oldPassword = cfg.getProperty(CFG_PASSWORD); + + // Set known values. + cfg.setProperty(CFG_USERNAME, USERNAME); + cfg.setProperty(CFG_PASSWORD, PASSWORD); + + EmailServiceImpl instance = (EmailServiceImpl) getService(EmailServiceImpl.class); + + PasswordAuthentication result = instance.getPasswordAuthentication(); + assertNotNull(" null returned", result); + assertEquals(" username does not match configuration", result.getUserName(), USERNAME); + assertEquals(" password does not match configuration", result.getPassword(), PASSWORD); + + // Restore old values, if any. + cfg.setProperty(CFG_USERNAME, oldUsername); + cfg.setProperty(CFG_PASSWORD, oldPassword); + } +} diff --git a/dspace-solr/pom.xml b/dspace-solr/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..a2906edb3dfe67661e666702b8721cc1ba1f0a44 --- /dev/null +++ b/dspace-solr/pom.xml @@ -0,0 +1,165 @@ +<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"> + + <!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright + ownership. The ASF licenses this file to you under the Apache + License, Version 2.0 (the "License"); you may not use this file + except in compliance with the License. You may obtain a copy of + the License at http://www.apache.org/licenses/LICENSE-2.0 Unless + required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + --> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.dspace</groupId> + <artifactId>dspace-parent</artifactId> + <version>4.1</version> + <relativePath>..</relativePath> + </parent> + + <groupId>org.dspace</groupId> + <artifactId>dspace-solr</artifactId> + <name>Apache Solr Webapp</name> + <description>Apache Solr Server</description> + <packaging>war</packaging> + + <properties> + <lucene.version>4.4.0</lucene.version> + <solr.version>4.4.0</solr.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> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>2.4</version> + <configuration> + <!-- This 'dspace-solr' WAR overlays the Apache Solr Web Application + available in Maven Central --> + <overlays> + <overlay> + <groupId>org.apache.solr</groupId> + <artifactId>solr</artifactId> + <!-- + Exclude the solr core named apache-solr-core, this is needed because the dspace-solr changes + need to take precendence over the solr-core, the solr-core will still be loaded in the solr-core.jar + --> + <excludes> + <exclude>WEB-INF/lib/apache-solr-core-${solr.version}.jar</exclude> + </excludes> + </overlay> + </overlays> + </configuration> + <executions> + <execution> + <!-- This execution creates a normal WAR (with all JARs, etc)--> + <id>webapp</id> + <configuration> + <primaryArtifact>true</primaryArtifact> + <archiveClasses>true</archiveClasses> + <attachClasses>true</attachClasses> + <classesClassifier>classes</classesClassifier> + <warSourceExcludes>WEB-INF/classes/**</warSourceExcludes> + <packagingExcludes> + WEB-INF/classes/**, + WEB-INF/lib/slf4j-jdk14-*.jar, + WEB-INF/lib/log4j-over-slf4j-*.jar + </packagingExcludes> + </configuration> + <goals> + <goal>war</goal> + </goals> + <phase>package</phase> + </execution> + <execution> + <!-- This execution creates a "skinny" WAR (without any JARs included)--> + <id>skinny</id> + <configuration> + <primaryArtifact>false</primaryArtifact> + <classifier>skinny</classifier> + <warSourceExcludes>WEB-INF/lib/**,WEB-INF/classes/**</warSourceExcludes> + <packagingExcludes>WEB-INF/lib/**,WEB-INF/classes/**</packagingExcludes> + </configuration> + <goals> + <goal>war</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> + + <dependencies> + <!-- Depends on the Apache 'solr' web application (see Overlay settings above)--> + <dependency> + <groupId>org.apache.solr</groupId> + <artifactId>solr</artifactId> + <version>${solr.version}</version> + <type>war</type> + </dependency> + <dependency> + <groupId>org.apache.solr</groupId> + <artifactId>solr-core</artifactId> + <version>${solr.version}</version> + <type>jar</type> + <exclusions> + <exclusion> + <groupId>jdk.tools</groupId> + <artifactId>jdk.tools</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.solr</groupId> + <artifactId>solr-solrj</artifactId> + <version>${solr.version}</version> + </dependency> + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-core</artifactId> + </dependency> + + <!-- Replace J.U.L. logging with log4j --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jul-to-slf4j</artifactId> + <version>1.6.1</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.6.1</version> + <scope>runtime</scope> + </dependency> + <dependency> + <artifactId>log4j</artifactId> + <groupId>log4j</groupId> + <type>jar</type> + <version>1.2.16</version> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.5</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>commons-logging</groupId> + <artifactId>commons-logging</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> + +</project> diff --git a/dspace-solr/src/main/java/org/apache/solr/handler/component/FacetComponent.java b/dspace-solr/src/main/java/org/apache/solr/handler/component/FacetComponent.java new file mode 100644 index 0000000000000000000000000000000000000000..9ced848b4f8856ca2d51df64a562d8520fb2593c --- /dev/null +++ b/dspace-solr/src/main/java/org/apache/solr/handler/component/FacetComponent.java @@ -0,0 +1,834 @@ +/** + * 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.apache.solr.handler.component; + +import org.apache.lucene.util.OpenBitSet; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.CommonParams; +import org.apache.solr.common.params.FacetParams; +import org.apache.solr.common.params.ModifiableSolrParams; +import org.apache.solr.common.params.SolrParams; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.common.util.StrUtils; +import org.apache.solr.request.SimpleFacets; +import org.apache.solr.schema.FieldType; +import org.apache.solr.search.QueryParsing; +import org.apache.solr.search.SyntaxError; + +import java.io.IOException; +import java.net.URL; +import java.util.*; + +/** + * TODO! + * + * @version $Id: FacetComponent.java 1152531 2011-07-31 00:43:33Z koji $ + * @since solr 1.3 + */ +public class FacetComponent extends SearchComponent +{ + public static final String COMPONENT_NAME = "facet"; + + @Override + public void prepare(ResponseBuilder rb) throws IOException + { + if (rb.req.getParams().getBool(FacetParams.FACET,false)) { + rb.setNeedDocSet( true ); + rb.doFacets = true; + } + } + + /** + * Actually run the query + * @param rb + */ + @Override + public void process(ResponseBuilder rb) throws IOException + { + if (rb.doFacets) { + SolrParams params = rb.req.getParams(); + SimpleFacets f = new SimpleFacets(rb.req, + rb.getResults().docSet, + params, + rb ); + + // TODO ???? add this directly to the response, or to the builder? + rb.rsp.add( "facet_counts", f.getFacetCounts() ); + } + } + + private static final String commandPrefix = "{!" + CommonParams.TERMS + "=$"; + + @Override + public int distributedProcess(ResponseBuilder rb) throws IOException { + if (!rb.doFacets) { + return ResponseBuilder.STAGE_DONE; + } + + if (rb.stage == ResponseBuilder.STAGE_GET_FIELDS) { + // overlap facet refinement requests (those shards that we need a count for + // particular facet values from), where possible, with + // the requests to get fields (because we know that is the + // only other required phase). + // We do this in distributedProcess so we can look at all of the + // requests in the outgoing queue at once. + + + + for (int shardNum=0; shardNum<rb.shards.length; shardNum++) { + List<String> refinements = null; + + for (DistribFieldFacet dff : rb._facetInfo.facets.values()) { + if (!dff.needRefinements) continue; + List<String> refList = dff._toRefine[shardNum]; + if (refList == null || refList.size()==0) continue; + + String key = dff.getKey(); // reuse the same key that was used for the main facet + String termsKey = key + "__terms"; + String termsVal = StrUtils.join(refList, ','); + + String facetCommand; + // add terms into the original facet.field command + // do it via parameter reference to avoid another layer of encoding. + + String termsKeyEncoded = QueryParsing.encodeLocalParamVal(termsKey); + if (dff.localParams != null) { + facetCommand = commandPrefix+termsKeyEncoded + " " + dff.facetStr.substring(2); + } else { + facetCommand = commandPrefix+termsKeyEncoded+'}'+dff.field; + } + + if (refinements == null) { + refinements = new ArrayList<String>(); + } + + refinements.add(facetCommand); + refinements.add(termsKey); + refinements.add(termsVal); + } + + if (refinements == null) continue; + + + String shard = rb.shards[shardNum]; + ShardRequest refine = null; + boolean newRequest = false; + + // try to find a request that is already going out to that shard. + // If nshards becomes to great, we way want to move to hashing for better + // scalability. + for (ShardRequest sreq : rb.outgoing) { + if ((sreq.purpose & ShardRequest.PURPOSE_GET_FIELDS)!=0 + && sreq.shards != null + && sreq.shards.length==1 + && sreq.shards[0].equals(shard)) + { + refine = sreq; + break; + } + } + + if (refine == null) { + // we didn't find any other suitable requests going out to that shard, so + // create one ourselves. + newRequest = true; + refine = new ShardRequest(); + refine.shards = new String[]{rb.shards[shardNum]}; + refine.params = new ModifiableSolrParams(rb.req.getParams()); + // don't request any documents + refine.params.remove(CommonParams.START); + refine.params.set(CommonParams.ROWS,"0"); + } + + refine.purpose |= ShardRequest.PURPOSE_REFINE_FACETS; + refine.params.set(FacetParams.FACET, "true"); + refine.params.remove(FacetParams.FACET_FIELD); + refine.params.remove(FacetParams.FACET_QUERY); + + for (int i=0; i<refinements.size();) { + String facetCommand=refinements.get(i++); + String termsKey=refinements.get(i++); + String termsVal=refinements.get(i++); + + refine.params.add(FacetParams.FACET_FIELD, facetCommand); + refine.params.set(termsKey, termsVal); + } + + if (newRequest) { + rb.addRequest(this, refine); + } + } + } + + return ResponseBuilder.STAGE_DONE; + } + + @Override + public void modifyRequest(ResponseBuilder rb, SearchComponent who, ShardRequest sreq) { + if (!rb.doFacets) return; + + if ((sreq.purpose & ShardRequest.PURPOSE_GET_TOP_IDS) != 0) { + sreq.purpose |= ShardRequest.PURPOSE_GET_FACETS; + + FacetInfo fi = rb._facetInfo; + if (fi == null) { + rb._facetInfo = fi = new FacetInfo(); + fi.parse(rb.req.getParams(), rb); + // should already be true... + // sreq.params.set(FacetParams.FACET, "true"); + } + + sreq.params.remove(FacetParams.FACET_MINCOUNT); + sreq.params.remove(FacetParams.FACET_OFFSET); + sreq.params.remove(FacetParams.FACET_LIMIT); + + for (DistribFieldFacet dff : fi.facets.values()) { + String paramStart = "f." + dff.field + '.'; + sreq.params.remove(paramStart + FacetParams.FACET_MINCOUNT); + sreq.params.remove(paramStart + FacetParams.FACET_OFFSET); + + dff.initialLimit = dff.limit <= 0 ? dff.limit : dff.offset + dff.limit; + + if (dff.sort.equals(FacetParams.FACET_SORT_COUNT)) { + if (dff.limit > 0) { + // set the initial limit higher to increase accuracy + dff.initialLimit = (int)(dff.initialLimit * 1.5) + 10; + dff.initialMincount = 0; // TODO: we could change this to 1, but would then need more refinement for small facet result sets? + } else { + // if limit==-1, then no need to artificially lower mincount to 0 if it's 1 + dff.initialMincount = Math.min(dff.minCount, 1); + } + } else { + // we're sorting by index order. + // if minCount==0, we should always be able to get accurate results w/o over-requesting or refining + // if minCount==1, we should be able to get accurate results w/o over-requesting, but we'll need to refine + // if minCount==n (>1), we can set the initialMincount to minCount/nShards, rounded up. + // For example, we know that if minCount=10 and we have 3 shards, then at least one shard must have a count of 4 for the term + // For the minCount>1 case, we can generate too short of a list (miss terms at the end of the list) unless limit==-1 + // For example: each shard could produce a list of top 10, but some of those could fail to make it into the combined list (i.e. + // we needed to go beyond the top 10 to generate the top 10 combined). Overrequesting can help a little here, but not as + // much as when sorting by count. + if (dff.minCount <= 1) { + dff.initialMincount = dff.minCount; + } else { + dff.initialMincount = (int)Math.ceil((double)dff.minCount / rb.shards.length); + // dff.initialMincount = 1; + } + } + + if (dff.initialMincount != 0) { + sreq.params.set(paramStart + FacetParams.FACET_MINCOUNT, dff.initialMincount); + } + + // Currently this is for testing only and allows overriding of the + // facet.limit set to the shards + dff.initialLimit = rb.req.getParams().getInt("facet.shard.limit", dff.initialLimit); + + sreq.params.set(paramStart + FacetParams.FACET_LIMIT, dff.initialLimit); + } + } else { + // turn off faceting on other requests + sreq.params.set(FacetParams.FACET, "false"); + // we could optionally remove faceting params + } + } + + @Override + public void handleResponses(ResponseBuilder rb, ShardRequest sreq) { + if (!rb.doFacets) return; + + if ((sreq.purpose & ShardRequest.PURPOSE_GET_FACETS)!=0) { + countFacets(rb, sreq); + } else if ((sreq.purpose & ShardRequest.PURPOSE_REFINE_FACETS)!=0) { + refineFacets(rb, sreq); + } + } + + + + + private void countFacets(ResponseBuilder rb, ShardRequest sreq) { + FacetInfo fi = rb._facetInfo; + + for (ShardResponse srsp: sreq.responses) { + int shardNum = rb.getShardNum(srsp.getShard()); + NamedList facet_counts = (NamedList)srsp.getSolrResponse().getResponse().get("facet_counts"); + + // handle facet queries + NamedList facet_queries = (NamedList)facet_counts.get("facet_queries"); + if (facet_queries != null) { + for (int i=0; i<facet_queries.size(); i++) { + String returnedKey = facet_queries.getName(i); + long count = ((Number)facet_queries.getVal(i)).longValue(); + QueryFacet qf = fi.queryFacets.get(returnedKey); + qf.count += count; + } + } + + // step through each facet.field, adding results from this shard + NamedList facet_fields = (NamedList)facet_counts.get("facet_fields"); + + if (facet_fields != null) { + for (DistribFieldFacet dff : fi.facets.values()) { + dff.add(shardNum, (NamedList)facet_fields.get(dff.getKey()), dff.initialLimit); + } + } + + // Distributed facet_dates + // + // The implementation below uses the first encountered shard's + // facet_dates as the basis for subsequent shards' data to be merged. + // (the "NOW" param should ensure consistency) + @SuppressWarnings("unchecked") + SimpleOrderedMap<SimpleOrderedMap<Object>> facet_dates = + (SimpleOrderedMap<SimpleOrderedMap<Object>>) + facet_counts.get("facet_dates"); + + if (facet_dates != null) { + + // go through each facet_date + for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_dates) { + final String field = entry.getKey(); + if (fi.dateFacets.get(field) == null) { + // first time we've seen this field, no merging + fi.dateFacets.add(field, entry.getValue()); + + } else { + // not the first time, merge current field + + SimpleOrderedMap<Object> shardFieldValues + = entry.getValue(); + SimpleOrderedMap<Object> existFieldValues + = fi.dateFacets.get(field); + + for (Map.Entry<String,Object> existPair : existFieldValues) { + final String key = existPair.getKey(); + if (key.equals("gap") || + key.equals("end") || + key.equals("start")) { + // we can skip these, must all be the same across shards + continue; + } + // can be null if inconsistencies in shards responses + Integer newValue = (Integer) shardFieldValues.get(key); + if (null != newValue) { + Integer oldValue = ((Integer) existPair.getValue()); + existPair.setValue(oldValue + newValue); + } + } + } + } + } + + // Distributed facet_ranges + // + // The implementation below uses the first encountered shard's + // facet_ranges as the basis for subsequent shards' data to be merged. + @SuppressWarnings("unchecked") + SimpleOrderedMap<SimpleOrderedMap<Object>> facet_ranges = + (SimpleOrderedMap<SimpleOrderedMap<Object>>) + facet_counts.get("facet_ranges"); + + if (facet_ranges != null) { + + // go through each facet_range + for (Map.Entry<String,SimpleOrderedMap<Object>> entry : facet_ranges) { + final String field = entry.getKey(); + if (fi.rangeFacets.get(field) == null) { + // first time we've seen this field, no merging + fi.rangeFacets.add(field, entry.getValue()); + + } else { + // not the first time, merge current field counts + + @SuppressWarnings("unchecked") + NamedList<Integer> shardFieldValues + = (NamedList<Integer>) entry.getValue().get("counts"); + + @SuppressWarnings("unchecked") + NamedList<Integer> existFieldValues + = (NamedList<Integer>) fi.rangeFacets.get(field).get("counts"); + + for (Map.Entry<String,Integer> existPair : existFieldValues) { + final String key = existPair.getKey(); + // can be null if inconsistencies in shards responses + Integer newValue = shardFieldValues.get(key); + if (null != newValue) { + Integer oldValue = existPair.getValue(); + existPair.setValue(oldValue + newValue); + } + } + } + } + } + } + + + // + // This code currently assumes that there will be only a single + // request ((with responses from all shards) sent out to get facets... + // otherwise we would need to wait until all facet responses were received. + // + + for (DistribFieldFacet dff : fi.facets.values()) { + // no need to check these facets for refinement + if (dff.initialLimit <= 0 && dff.initialMincount == 0) continue; + + // only other case where index-sort doesn't need refinement is if minCount==0 + if (dff.minCount == 0 && dff.sort.equals(FacetParams.FACET_SORT_INDEX)) continue; + + @SuppressWarnings("unchecked") // generic array's are annoying + List<String>[] tmp = (List<String>[]) new List[rb.shards.length]; + dff._toRefine = tmp; + + ShardFacetCount[] counts = dff.getCountSorted(); + int ntop = Math.min(counts.length, dff.limit >= 0 ? dff.offset + dff.limit : Integer.MAX_VALUE); + long smallestCount = counts.length == 0 ? 0 : counts[ntop-1].count; + + for (int i=0; i<counts.length; i++) { + ShardFacetCount sfc = counts[i]; + boolean needRefinement = false; + + if (i<ntop) { + // automatically flag the top values for refinement + // this should always be true for facet.sort=index + needRefinement = true; + } else { + // this logic should only be invoked for facet.sort=index (for now) + + // calculate the maximum value that this term may have + // and if it is >= smallestCount, then flag for refinement + long maxCount = sfc.count; + for (int shardNum=0; shardNum<rb.shards.length; shardNum++) { + OpenBitSet obs = dff.counted[shardNum]; + if (!obs.get(sfc.termNum)) { + // if missing from this shard, add the max it could be + maxCount += dff.maxPossible(sfc,shardNum); + } + } + if (maxCount >= smallestCount) { + // TODO: on a tie, we could check the term values + needRefinement = true; + } + } + + if (needRefinement) { + // add a query for each shard missing the term that needs refinement + for (int shardNum=0; shardNum<rb.shards.length; shardNum++) { + OpenBitSet obs = dff.counted[shardNum]; + if (!obs.get(sfc.termNum) && dff.maxPossible(sfc,shardNum)>0) { + dff.needRefinements = true; + List<String> lst = dff._toRefine[shardNum]; + if (lst == null) { + lst = dff._toRefine[shardNum] = new ArrayList<String>(); + } + lst.add(sfc.name); + } + } + } + } + } + } + + + private void refineFacets(ResponseBuilder rb, ShardRequest sreq) { + FacetInfo fi = rb._facetInfo; + + for (ShardResponse srsp: sreq.responses) { + // int shardNum = rb.getShardNum(srsp.shard); + NamedList facet_counts = (NamedList)srsp.getSolrResponse().getResponse().get("facet_counts"); + NamedList facet_fields = (NamedList)facet_counts.get("facet_fields"); + + if (facet_fields == null) continue; // this can happen when there's an exception + + for (int i=0; i<facet_fields.size(); i++) { + String key = facet_fields.getName(i); + DistribFieldFacet dff = fi.facets.get(key); + if (dff == null) continue; + + NamedList shardCounts = (NamedList)facet_fields.getVal(i); + + for (int j=0; j<shardCounts.size(); j++) { + String name = shardCounts.getName(j); + long count = ((Number)shardCounts.getVal(j)).longValue(); + ShardFacetCount sfc = dff.counts.get(name); + sfc.count += count; + } + } + } + } + + @Override + public void finishStage(ResponseBuilder rb) { + if (!rb.doFacets || rb.stage != ResponseBuilder.STAGE_GET_FIELDS) return; + // wait until STAGE_GET_FIELDS + // so that "result" is already stored in the response (for aesthetics) + + + FacetInfo fi = rb._facetInfo; + + NamedList<Object> facet_counts = new SimpleOrderedMap<Object>(); + + NamedList facet_queries = new SimpleOrderedMap(); + facet_counts.add("facet_queries",facet_queries); + for (QueryFacet qf : fi.queryFacets.values()) { + facet_queries.add(qf.getKey(), num(qf.count)); + } + + NamedList<Object> facet_fields = new SimpleOrderedMap<Object>(); + facet_counts.add("facet_fields", facet_fields); + + for (DistribFieldFacet dff : fi.facets.values()) { + NamedList<Object> fieldCounts = new NamedList<Object>(); // order is more important for facets + facet_fields.add(dff.getKey(), fieldCounts); + + ShardFacetCount[] counts; + boolean countSorted = dff.sort.equals(FacetParams.FACET_SORT_COUNT); + if (countSorted) { + counts = dff.countSorted; + if (counts == null || dff.needRefinements) { + counts = dff.getCountSorted(); + } + } else if (dff.sort.equals(FacetParams.FACET_SORT_INDEX)) { + counts = dff.getLexSorted(); + } else { // TODO: log error or throw exception? + counts = dff.getLexSorted(); + } + + if (countSorted) { + int end = dff.limit < 0 ? counts.length : Math.min(dff.offset + dff.limit, counts.length); + for (int i=dff.offset; i<end; i++) { + if (counts[i].count < dff.minCount) { + break; + } + fieldCounts.add(counts[i].name, num(counts[i].count)); + } + } else { + int off = dff.offset; + int lim = dff.limit >= 0 ? dff.limit : Integer.MAX_VALUE; + + // index order... + for (int i=0; i<counts.length; i++) { + long count = counts[i].count; + if (count < dff.minCount) continue; + if (off > 0) { + off--; + continue; + } + if (lim <= 0) { + break; + } + lim--; + fieldCounts.add(counts[i].name, num(count)); + } + } + + if (dff.missing) { + fieldCounts.add(null, num(dff.missingCount)); + } + } + + facet_counts.add("facet_dates", fi.dateFacets); + facet_counts.add("facet_ranges", fi.rangeFacets); + + rb.rsp.add("facet_counts", facet_counts); + + rb._facetInfo = null; // could be big, so release asap + } + + + // use <int> tags for smaller facet counts (better back compatibility) + private Number num(long val) { + if (val < Integer.MAX_VALUE) return (int)val; + else return val; + } + private Number num(Long val) { + if (val.longValue() < Integer.MAX_VALUE) return val.intValue(); + else return val; + } + + + ///////////////////////////////////////////// + /// SolrInfoMBean + //////////////////////////////////////////// + + @Override + public String getDescription() { + return "Handle Faceting"; + } + + @Override + public String getVersion() { + return "$Revision: 1152531 $"; + } + + + public String getSourceId() { + return "$Id: FacetComponent.java 1152531 2011-07-31 00:43:33Z koji $"; + } + + @Override + public String getSource() { + return "$URL: http://svn.apache.org/repos/asf/lucene/dev/tags/lucene_solr_3_5_0/solr/core/src/java/org/apache/solr/handler/component/FacetComponent.java $"; + } + + @Override + public URL[] getDocs() { + return null; + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class FacetInfo { + public LinkedHashMap<String,QueryFacet> queryFacets; + public LinkedHashMap<String,DistribFieldFacet> facets; + public SimpleOrderedMap<SimpleOrderedMap<Object>> dateFacets + = new SimpleOrderedMap<SimpleOrderedMap<Object>>(); + public SimpleOrderedMap<SimpleOrderedMap<Object>> rangeFacets + = new SimpleOrderedMap<SimpleOrderedMap<Object>>(); + + public List exceptionList; + + void parse(SolrParams params, ResponseBuilder rb) { + queryFacets = new LinkedHashMap<String,QueryFacet>(); + facets = new LinkedHashMap<String,DistribFieldFacet>(); + + String[] facetQs = params.getParams(FacetParams.FACET_QUERY); + if (facetQs != null) { + for (String query : facetQs) { + QueryFacet queryFacet = new QueryFacet(rb, query); + queryFacets.put(queryFacet.getKey(), queryFacet); + } + } + + String[] facetFs = params.getParams(FacetParams.FACET_FIELD); + if (facetFs != null) { + + for (String field : facetFs) { + DistribFieldFacet ff = new DistribFieldFacet(rb, field); + facets.put(ff.getKey(), ff); + } + } + } + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class FacetBase { + String facetType; // facet.field, facet.query, etc (make enum?) + String facetStr; // original parameter value of facetStr + String facetOn; // the field or query, absent localParams if appropriate + private String key; // label in the response for the result... "foo" for {!key=foo}myfield + SolrParams localParams; // any local params for the facet + + public FacetBase(ResponseBuilder rb, String facetType, String facetStr) { + this.facetType = facetType; + this.facetStr = facetStr; + try + { + this.localParams = QueryParsing.getLocalParams(facetStr, + rb.req.getParams()); + } + catch (SyntaxError e) + { + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, e); + } + this.facetOn = facetStr; + this.key = facetStr; + + if (localParams != null) { + // remove local params unless it's a query + if (!facetType.equals(FacetParams.FACET_QUERY)) { + facetOn = localParams.get(CommonParams.VALUE); + key = facetOn; + } + + key = localParams.get(CommonParams.OUTPUT_KEY, key); + } + } + + /** returns the key in the response that this facet will be under */ + public String getKey() { return key; } + public String getType() { return facetType; } + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class QueryFacet extends FacetBase { + public long count; + + public QueryFacet(ResponseBuilder rb, String facetStr) { + super(rb, FacetParams.FACET_QUERY, facetStr); + } + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class FieldFacet extends FacetBase { + public String field; // the field to facet on... "myfield" for {!key=foo}myfield + public FieldType ftype; + public int offset; + public int limit; + public int minCount; + public String sort; + public boolean missing; + public String prefix; + public long missingCount; + + public FieldFacet(ResponseBuilder rb, String facetStr) { + super(rb, FacetParams.FACET_FIELD, facetStr); + fillParams(rb, rb.req.getParams(), facetOn); + } + + private void fillParams(ResponseBuilder rb, SolrParams params, String field) { + this.field = field; + this.ftype = rb.req.getSchema().getFieldTypeNoEx(this.field); + this.offset = params.getFieldInt(field, FacetParams.FACET_OFFSET, 0); + this.limit = params.getFieldInt(field, FacetParams.FACET_LIMIT, 100); + Integer mincount = params.getFieldInt(field, FacetParams.FACET_MINCOUNT); + if (mincount==null) { + Boolean zeros = params.getFieldBool(field, FacetParams.FACET_ZEROS); + // mincount = (zeros!=null && zeros) ? 0 : 1; + mincount = (zeros!=null && !zeros) ? 1 : 0; + // current default is to include zeros. + } + this.minCount = mincount; + this.missing = params.getFieldBool(field, FacetParams.FACET_MISSING, false); + // default to sorting by count if there is a limit. + this.sort = params.getFieldParam(field, FacetParams.FACET_SORT, limit>0 ? FacetParams.FACET_SORT_COUNT : FacetParams.FACET_SORT_INDEX); + if (this.sort.equals(FacetParams.FACET_SORT_COUNT_LEGACY)) { + this.sort = FacetParams.FACET_SORT_COUNT; + } else if (this.sort.equals(FacetParams.FACET_SORT_INDEX_LEGACY)) { + this.sort = FacetParams.FACET_SORT_INDEX; + } + this.prefix = params.getFieldParam(field,FacetParams.FACET_PREFIX); + } + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class DistribFieldFacet extends FieldFacet { + public List<String>[] _toRefine; // a List<String> of refinements needed, one for each shard. + + // SchemaField sf; // currently unneeded + + // the max possible count for a term appearing on no list + public long missingMaxPossible; + // the max possible count for a missing term for each shard (indexed by shardNum) + public long[] missingMax; + public OpenBitSet[] counted; // a bitset for each shard, keeping track of which terms seen + public HashMap<String,ShardFacetCount> counts = new HashMap<String,ShardFacetCount>(128); + public int termNum; + + public int initialLimit; // how many terms requested in first phase + public int initialMincount; // mincount param sent to each shard + public boolean needRefinements; + public ShardFacetCount[] countSorted; + + DistribFieldFacet(ResponseBuilder rb, String facetStr) { + super(rb, facetStr); + // sf = rb.req.getSchema().getField(field); + missingMax = new long[rb.shards.length]; + counted = new OpenBitSet[rb.shards.length]; + } + + void add(int shardNum, NamedList shardCounts, int numRequested) { + // shardCounts could be null if there was an exception + int sz = shardCounts == null ? 0 : shardCounts.size(); + int numReceived = sz; + + OpenBitSet terms = new OpenBitSet(termNum+sz); + + long last = 0; + for (int i=0; i<sz; i++) { + String name = shardCounts.getName(i); + long count = ((Number)shardCounts.getVal(i)).longValue(); + if (name == null) { + missingCount += count; + numReceived--; + } else { + ShardFacetCount sfc = counts.get(name); + if (sfc == null) { + sfc = new ShardFacetCount(); + sfc.name = name; + sfc.indexed = ftype == null ? sfc.name : ftype.toInternal(sfc.name); + sfc.termNum = termNum++; + counts.put(name, sfc); + } + sfc.count += count; + terms.fastSet(sfc.termNum); + last = count; + } + } + + // the largest possible missing term is initialMincount if we received less + // than the number requested. + if (numRequested<0 || numRequested != 0 && numReceived < numRequested) { + last = initialMincount; + } + + missingMaxPossible += last; + missingMax[shardNum] = last; + counted[shardNum] = terms; + } + + public ShardFacetCount[] getLexSorted() { + ShardFacetCount[] arr = counts.values().toArray(new ShardFacetCount[counts.size()]); + Arrays.sort(arr, new Comparator<ShardFacetCount>() { + public int compare(ShardFacetCount o1, ShardFacetCount o2) { + return o1.indexed.compareTo(o2.indexed); + } + }); + countSorted = arr; + return arr; + } + + public ShardFacetCount[] getCountSorted() { + ShardFacetCount[] arr = counts.values().toArray(new ShardFacetCount[counts.size()]); + Arrays.sort(arr, new Comparator<ShardFacetCount>() { + public int compare(ShardFacetCount o1, ShardFacetCount o2) { + if (o2.count < o1.count) return -1; + else if (o1.count < o2.count) return 1; + return o1.indexed.compareTo(o2.indexed); + } + }); + countSorted = arr; + return arr; + } + + // returns the max possible value this ShardFacetCount could have for this shard + // (assumes the shard did not report a count for this value) + long maxPossible(ShardFacetCount sfc, int shardNum) { + return missingMax[shardNum]; + // TODO: could store the last term in the shard to tell if this term + // comes before or after it. If it comes before, we could subtract 1 + } + } + + /** + * <b>This API is experimental and subject to change</b> + */ + public static class ShardFacetCount { + public String name; + public String indexed; // the indexed form of the name... used for comparisons. + public long count; + public int termNum; // term number starting at 0 (used in bit arrays) + + @Override + public String toString() { + return "{term="+name+",termNum="+termNum+",count="+count+"}"; + } + } +} diff --git a/dspace-solr/src/main/java/org/dspace/solr/filters/ConfigureLog4jListener.java b/dspace-solr/src/main/java/org/dspace/solr/filters/ConfigureLog4jListener.java new file mode 100644 index 0000000000000000000000000000000000000000..9d87ac27ff7348535a1b773142492788fe4475c3 --- /dev/null +++ b/dspace-solr/src/main/java/org/dspace/solr/filters/ConfigureLog4jListener.java @@ -0,0 +1,87 @@ +/** + * 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.solr.filters; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import org.apache.log4j.Hierarchy; +import org.apache.log4j.Level; +import org.apache.log4j.PropertyConfigurator; +import org.apache.log4j.helpers.Loader; +import org.apache.log4j.spi.Configurator; +import org.apache.log4j.spi.RootLogger; +import org.apache.log4j.xml.DOMConfigurator; + +/** + * Initialize Log4J at application startup. + * This class mimics the default Log4J initialization procedure, except + * that it is controlled by context parameters rather than system properties. + * + * @author Mark H. Wood + */ +public class ConfigureLog4jListener + implements ServletContextListener +{ + public void contextInitialized(ServletContextEvent sce) + { + ServletContext ctx = sce.getServletContext(); + + String logConfig = ctx.getInitParameter("log4j.configuration"); + if (null == logConfig) + logConfig = "log4j.properties"; + + URL configURL; + try { + configURL = new File(logConfig).toURI().toURL(); + } catch (MalformedURLException e) { + configURL = Loader.getResource(logConfig); + } + + if (null == configURL) + { + ctx.log("Log4J configuration not found. Left unconfigured."); + return; + } + else + { + ctx.log(" In context " + ctx.getContextPath() + + ", configuring Log4J from " + configURL.toExternalForm()); + + String configuratorName = ctx.getInitParameter("log4j.configuratorClass"); + if (null != configuratorName) + { + Configurator configurator; + try + { + configurator = (Configurator) Class.forName(configuratorName).newInstance(); + } catch (Exception ex) + { + ctx.log("Unable to load custom Log4J configuration class '" + + configuratorName + "': " + ex.getMessage()); + return; + } + + configurator.doConfigure(configURL, new Hierarchy(new RootLogger(Level.OFF))); + } + else if (configURL.getFile().endsWith(".xml")) + DOMConfigurator.configure(configURL); + else + PropertyConfigurator.configure(configURL); + } + } + + public void contextDestroyed(ServletContextEvent sce) + { + // Nothing to be done + } +} diff --git a/dspace-solr/src/main/java/org/dspace/solr/filters/LocalHostRestrictionFilter.java b/dspace-solr/src/main/java/org/dspace/solr/filters/LocalHostRestrictionFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..723aee5313e2f54575e3544c138739104b110df4 --- /dev/null +++ b/dspace-solr/src/main/java/org/dspace/solr/filters/LocalHostRestrictionFilter.java @@ -0,0 +1,65 @@ +/** + * 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.solr.filters; + +import java.io.IOException; +import java.net.InetAddress; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + +public class LocalHostRestrictionFilter implements Filter { + + private boolean enabled = true; + + public LocalHostRestrictionFilter() { + // TODO Auto-generated constructor stub + } + + public void destroy() { + // TODO Auto-generated method stub + + } + + public void doFilter(ServletRequest request, ServletResponse response, + FilterChain chain) throws IOException, ServletException { + + if(enabled){ + InetAddress ia = InetAddress.getLocalHost(); + String localAddr = ia.getHostAddress(); + String remoteAddr = request.getRemoteAddr(); + + if(!(localAddr.equals(remoteAddr) || remoteAddr.equals("127.0.0.1") || remoteAddr.startsWith("0:0:0:0:0:0:0:1"))) + { + ((HttpServletResponse)response).sendError(403); + return; + } + + } + + chain.doFilter(request, response); + } + + /** + * + */ + public void init(FilterConfig arg0) throws ServletException { + String restrict = arg0.getServletContext().getInitParameter("LocalHostRestrictionFilter.localhost"); + if("false".equalsIgnoreCase(restrict)) + { + enabled = false; + } + + } + +} diff --git a/dspace-solr/src/main/webapp/WEB-INF/web.xml b/dspace-solr/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..174d275728302d5c0856ff70bd1b6007c5f6a22b --- /dev/null +++ b/dspace-solr/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,203 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> +<!-- + + 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/ + +--> + +<web-app> + + <!-- Uncomment if you are trying to use a Resin version before 3.0.19. + Their XML implementation isn't entirely compatible with Xerces. + Below are the implementations to use with Sun's JVM. + <system-property javax.xml.xpath.XPathFactory= + "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl"/> + <system-property javax.xml.parsers.DocumentBuilderFactory= + "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"/> + <system-property javax.xml.parsers.SAXParserFactory= + "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"/> + --> + + <!-- People who want to hardcode their "Solr Home" directly into the + WAR File can set the JNDI property here... + --> + <!-- + <env-entry> + <env-entry-name>solr/home</env-entry-name> + <env-entry-value>/put/your/solr/home/here</env-entry-value> + <env-entry-type>java.lang.String</env-entry-type> + </env-entry> + --> + + <context-param> + <param-name>log4j.configuration</param-name> + <param-value>${dspace.dir}/config/log4j-solr.properties</param-value> + <description>URL locating a Log4J configuration file (properties or XML).</description> + </context-param> + + <!-- Any path (name) registered in solrconfig.xml will be sent to that filter --> + <filter> + <filter-name>LocalHostRestrictionFilter</filter-name> + <filter-class>org.dspace.solr.filters.LocalHostRestrictionFilter</filter-class> + </filter> + + <!-- Any path (name) registered in solrconfig.xml will be sent to that filter --> + <filter> + <filter-name>SolrRequestFilter</filter-name> + <filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class> + <!-- If you are wiring Solr into a larger web application which controls + the web context root, you will probably want to mount Solr under + a path prefix (app.war with /app/solr mounted into it, for example). + You will need to put this prefix in front of the SolrDispatchFilter + url-pattern mapping too (/solr/*), and also on any paths for + legacy Solr servlet mappings you may be using. + For the Admin UI to work properly in a path-prefixed configuration, + the admin folder containing the resources needs to be under the app context root + named to match the path-prefix. For example: + + .war + xxx + js + main.js + --> + <!-- + <init-param> + <param-name>path-prefix</param-name> + <param-value>/xxx</param-value> + </init-param> + --> + </filter> + + + <filter-mapping> + <filter-name>LocalHostRestrictionFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + + <filter-mapping> + <!-- + NOTE: When using multicore, /admin JSP URLs with a core specified + such as /solr/coreName/admin/stats.jsp get forwarded by a + RequestDispatcher to /solr/admin/stats.jsp with the specified core + put into request scope keyed as "org.apache.solr.SolrCore". + + It is unnecessary, and potentially problematic, to have the SolrDispatchFilter + configured to also filter on forwards. Do not configure + this dispatcher as <dispatcher>FORWARD</dispatcher>. + --> + <filter-name>SolrRequestFilter</filter-name> + <url-pattern>/*</url-pattern> + </filter-mapping> + + <!-- Otherwise it will continue to the old servlets --> + + <listener> + <listener-class>org.dspace.solr.filters.ConfigureLog4jListener</listener-class> + </listener> + + <servlet> + <servlet-name>Zookeeper</servlet-name> + <servlet-class>org.apache.solr.servlet.ZookeeperInfoServlet</servlet-class> + </servlet> + + <servlet> + <servlet-name>LoadAdminUI</servlet-name> + <servlet-class>org.apache.solr.servlet.LoadAdminUiServlet</servlet-class> + </servlet> + + <!-- Remove in Solr 5.0 --> + <!-- This sends SC_MOVED_PERMANENTLY (301) for resources that changed in 4.0 --> + <servlet> + <servlet-name>RedirectOldAdminUI</servlet-name> + <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class> + <init-param> + <param-name>destination</param-name> + <param-value>${context}/#/</param-value> + </init-param> + </servlet> + + <servlet> + <servlet-name>RedirectOldZookeeper</servlet-name> + <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class> + <init-param> + <param-name>destination</param-name> + <param-value>${context}/zookeeper</param-value> + </init-param> + </servlet> + + <servlet> + <servlet-name>RedirectLogging</servlet-name> + <servlet-class>org.apache.solr.servlet.RedirectServlet</servlet-class> + <init-param> + <param-name>destination</param-name> + <param-value>${context}/#/~logging</param-value> + </init-param> + </servlet> + + <servlet> + <servlet-name>SolrRestApi</servlet-name> + <servlet-class>org.restlet.ext.servlet.ServerServlet</servlet-class> + <init-param> + <param-name>org.restlet.application</param-name> + <param-value>org.apache.solr.rest.SolrRestApi</param-value> + </init-param> + </servlet> + + <servlet-mapping> + <servlet-name>RedirectOldAdminUI</servlet-name> + <url-pattern>/admin/</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>RedirectOldAdminUI</servlet-name> + <url-pattern>/admin</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>RedirectOldZookeeper</servlet-name> + <url-pattern>/zookeeper.jsp</url-pattern> + </servlet-mapping> + <servlet-mapping> + <servlet-name>RedirectLogging</servlet-name> + <url-pattern>/logging</url-pattern> + </servlet-mapping> + + <!-- Servlet Mapping --> + <servlet-mapping> + <servlet-name>Zookeeper</servlet-name> + <url-pattern>/zookeeper</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>LoadAdminUI</servlet-name> + <url-pattern>/admin.html</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>SolrRestApi</servlet-name> + <url-pattern>/schema/*</url-pattern> + </servlet-mapping> + + <mime-mapping> + <extension>.xsl</extension> + <!-- per http://www.w3.org/TR/2006/PR-xslt20-20061121/ --> + <mime-type>application/xslt+xml</mime-type> + </mime-mapping> + + <welcome-file-list> + <welcome-file>admin.html</welcome-file> + </welcome-file-list> + + <!-- People who want to hardcode their "Solr Home" directly into the + WAR File can set the JNDI property here... + --> + <env-entry> + <env-entry-name>solr/home</env-entry-name> + <env-entry-value>${dspace.dir}/solr</env-entry-value> + <env-entry-type>java.lang.String</env-entry-type> + </env-entry> + +</web-app> 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/AbstractSimpleDC.java b/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSimpleDC.java new file mode 100644 index 0000000000000000000000000000000000000000..e88f86ff1c89ff20a04d8615b8eea6be56904a67 --- /dev/null +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSimpleDC.java @@ -0,0 +1,97 @@ +/** + * 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.sword2; + +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; + +import java.util.HashMap; +import java.util.Properties; + +public class AbstractSimpleDC +{ + protected HashMap<String, String> dcMap = null; + protected HashMap<String, String> atomMap = null; + + protected void loadMetadataMaps() + { + if (this.dcMap == null) + { + // 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); + } + } + } + + if (this.atomMap == null) + { + this.atomMap = new HashMap<String, String>(); + Properties props = ConfigurationManager.getProperties("swordv2-server"); + for (Object key : props.keySet()) + { + String keyString = (String) key; + if (keyString.startsWith("atom.")) + { + String k = keyString.substring("atom.".length()); + String v = (String) props.get(key); + this.atomMap.put(k, v); + } + } + } + } + + protected SimpleDCMetadata getMetadata(Item item) + { + this.loadMetadataMaps(); + + SimpleDCMetadata md = new SimpleDCMetadata(); + DCValue[] all = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); + + for (DCValue dcv : all) + { + String valueMatch = dcv.schema + "." + dcv.element; + if (dcv.qualifier != null) + { + valueMatch += "." + dcv.qualifier; + } + + // look for the metadata in the dublin core map + for (String key : this.dcMap.keySet()) + { + String value = this.dcMap.get(key); + if (valueMatch.equals(value)) + { + md.addDublinCore(key, dcv.value); + } + } + + // look for the metadata in the atom map + for (String key : this.atomMap.keySet()) + { + String value = this.atomMap.get(key); + if (valueMatch.equals(value)) + { + md.addAtom(key, dcv.value); + } + } + } + + return md; + } +} 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/SimpleDCMetadata.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCMetadata.java new file mode 100644 index 0000000000000000000000000000000000000000..db57f3e3f9315a3c07d1ce9d531c43b9e8085f7a --- /dev/null +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCMetadata.java @@ -0,0 +1,38 @@ +/** + * 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.sword2; + +import java.util.HashMap; +import java.util.Map; + +public class SimpleDCMetadata +{ + private Map<String, String> dublinCore = new HashMap<String, String>(); + private Map<String, String> atom = new HashMap<String, String>(); + + public void addDublinCore(String element, String value) + { + this.dublinCore.put(element, value); + } + + public void addAtom(String element, String value) + { + this.atom.put(element, value); + } + + public Map<String, String> getDublinCore() + { + return dublinCore; + } + + public Map<String, String> getAtom() + { + return atom; + } +} 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/SwordMETSPackageIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSPackageIngester.java new file mode 100644 index 0000000000000000000000000000000000000000..0fe5c9f8282635860c52fe280d7361aac56d6117 --- /dev/null +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSPackageIngester.java @@ -0,0 +1,47 @@ +/** + * 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.sword2; + + +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.dspace.content.packager.DSpaceMETSIngester; +import org.dspace.content.packager.PackageParameters; +import org.dspace.content.packager.PackageUtils; +import org.dspace.content.packager.PackageValidationException; +import org.dspace.core.Context; + +import java.io.IOException; +import java.sql.SQLException; + +public class SwordMETSPackageIngester extends DSpaceMETSIngester +{ + /** + * Policy: For DSpace deposit license, take deposit license + * supplied by explicit argument first, else use collection's + * default deposit license. + * For Creative Commons, look for a rightsMd containing a CC license. + * + * This override basically fixes a bug in the DSpaceMETSIngester which + * allows (in fact enforces) a null licence during replace, but which + * then requires it to be not-null here. + * + */ + @Override + public void addLicense(Context context, Item item, String license, + Collection collection, PackageParameters params) + throws PackageValidationException, + AuthorizeException, SQLException, IOException + { + if (PackageUtils.findDepositLicense(context, item) == null && license != null) + { + PackageUtils.addDepositLicense(context, license, item, collection); + } + } +} 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/WorkflowManagerUnrestricted.java b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerUnrestricted.java new file mode 100644 index 0000000000000000000000000000000000000000..cd7d2dbcffc210d02a612ab378a2260758bfa4d1 --- /dev/null +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerUnrestricted.java @@ -0,0 +1,209 @@ +/** + * 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.sword2; + +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; +import org.swordapp.server.UriRegistry; + +import java.sql.SQLException; + +/** + * This implementation of WorkflowManager is unrestricted and allows UPDATE and DELETE operations + * on items in any state (in workflow, in archive, or withdrawn). + */ +public class WorkflowManagerUnrestricted implements WorkflowManager +{ + public void retrieveServiceDoc(Context context) throws SwordError + { + // do nothing - operation allowed + } + + public void listCollectionContents(Context context, Collection collection) throws SwordError + { + // do nothing - operation allowed + } + + public void createResource(Context context, Collection collection) throws SwordError + { + // do nothing - operation allowed + } + + public void retrieveContent(Context context, Item item) throws SwordError + { + // do nothing - operation allowed + } + + public void retrieveBitstream(Context context, Bitstream bitstream) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void replaceResourceContent(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void replaceMetadata(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void replaceMetadataAndMediaResource(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void deleteMediaResource(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void deleteBitstream(Context context, Bitstream bitstream) throws SwordError, DSpaceSwordException + { + // this is equivalent to asking whether the media resource in the item can be deleted + try + { + for (Bundle bundle : bitstream.getBundles()) + { + // is the bitstream in the ORIGINAL bundle? If not, it can't be worked on + if (!"ORIGINAL".equals(bundle.getName())) + { + throw new SwordError(UriRegistry.ERROR_METHOD_NOT_ALLOWED, "The file is not in a bundle which can be modified"); + } + + for (Item item : bundle.getItems()) + { + this.deleteMediaResource(context, item); + } + } + } + catch (SQLException e) + { + throw new DSpaceSwordException(e); + } + } + + public void replaceBitstream(Context context, Bitstream bitstream) + throws SwordError, DSpaceSwordException + { + // this is equivalent to asking whether the media resource in the item can be deleted + try + { + for (Bundle bundle : bitstream.getBundles()) + { + // is the bitstream in the ORIGINAL bundle? If not, it can't be worked on + if (!"ORIGINAL".equals(bundle.getName())) + { + throw new SwordError(UriRegistry.ERROR_METHOD_NOT_ALLOWED, "The file is not in a bundle which can be modified"); + } + + for (Item item : bundle.getItems()) + { + this.replaceResourceContent(context, item); + } + } + } + catch (SQLException e) + { + throw new DSpaceSwordException(e); + } + } + + public void addResourceContent(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void addMetadata(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void deleteItem(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void retrieveStatement(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void modifyState(Context context, Item item) throws SwordError, DSpaceSwordException + { + // do nothing - operation allowed + } + + public void resolveState(Context context, Deposit deposit, DepositResult result, VerboseDescription verboseDescription) + throws DSpaceSwordException + { + this.resolveState(context, deposit, result, verboseDescription, true); + } + + public void resolveState(Context context, Deposit deposit, DepositResult result, VerboseDescription verboseDescription, boolean containerOperation) + throws DSpaceSwordException + { + // the containerOperation flag tells us whether this method was called by an operation which happened on the + // container. This workflow implementation only changes workflow states on contaner operations, not media + // resource operations, so we just bounce this right back. + if (!containerOperation) + { + return; + } + + // if we get to here this is a container operation, and we can decide how best to process + Item item = result.getItem(); + + // find out where the item is in the workflow + WorkflowTools wft = new WorkflowTools(); + boolean inwf = wft.isItemInWorkflow(context, item); + boolean inws = wft.isItemInWorkspace(context, item); + + // or find out if the item is in the archive + boolean inarch = item.isArchived() || item.isWithdrawn(); + + // in progress inws inwf inarch action description + // 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 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, and the item is already in the archive"); + // throw new DSpaceSwordException("Invalid workflow state"); + } + + if (!deposit.isInProgress() && inws) + { + verboseDescription.append("The deposit is finished: moving it from the workspace to the workflow"); + wft.startWorkflow(context, item); + } + + if (deposit.isInProgress() && inarch) + { + 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) + { + verboseDescription.append("The deposit is in progress, but is in the workflow; returning to the workspace"); + wft.stopWorkflow(context, item); + } + } +} 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/DiscoverySearchRequestProcessor.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/DiscoverySearchRequestProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..2d23327ea9923cf9f46cbb24ee41330d05597032 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/DiscoverySearchRequestProcessor.java @@ -0,0 +1,47 @@ +/** + * 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.administrative.mapper; + +import java.io.IOException; +import java.util.List; +import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.discovery.DiscoverQuery; +import org.dspace.discovery.DiscoverResult; +import org.dspace.discovery.SearchServiceException; +import org.dspace.discovery.SearchUtils; + +/** + * Search using the Discovery index provider. + * + * @author mwood + */ +public class DiscoverySearchRequestProcessor + implements SearchRequestProcessor +{ + @Override + public List<DSpaceObject> doItemMapSearch(Context context, String queryString, + Collection collection) + throws IOException + { + DiscoverQuery query = new DiscoverQuery(); + query.setQuery(queryString); + query.addFilterQueries("-location:l"+collection.getID()); + + DiscoverResult results = null; + try { + results = SearchUtils.getSearchService().search(context, query); + } catch (SearchServiceException ex) { + throw new IOException(ex); // Best we can do with the interface method's signature + } + + return results.getDspaceObjects(); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/LuceneSearchRequestProcessor.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/LuceneSearchRequestProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..f5d7128f0643f0412e9abeca757c418b780748ce --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/LuceneSearchRequestProcessor.java @@ -0,0 +1,47 @@ +/** + * 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.administrative.mapper; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; +import org.dspace.search.DSQuery; +import org.dspace.search.QueryArgs; +import org.dspace.search.QueryResults; + +/** + * Search using built-in Lucene index provider. + * + * @author mwood + */ +public class LuceneSearchRequestProcessor + implements SearchRequestProcessor +{ + @Override + public List<DSpaceObject> doItemMapSearch(Context context, String query, Collection collection) + throws IOException, SQLException + { + QueryArgs queryArgs = new QueryArgs(); + queryArgs.setQuery(query); + queryArgs.setPageSize(Integer.MAX_VALUE); + QueryResults results = DSQuery.doQuery(context, queryArgs); + + results.getHitHandles(); + List<DSpaceObject> dsos = new ArrayList<DSpaceObject>(); + for (String handle : results.getHitHandles()) + dsos.add(HandleManager.resolveToObject(context, handle)); + + return dsos; + } +} 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/administrative/mapper/SearchRequestProcessor.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchRequestProcessor.java new file mode 100644 index 0000000000000000000000000000000000000000..5cb5f9d80c7817c77012b7e7e30fd3976b7f2232 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchRequestProcessor.java @@ -0,0 +1,38 @@ +/** + * 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.administrative.mapper; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; +import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Context; +import org.dspace.search.QueryResults; + +/** + * Generic search. See plug-ins derived from this interface. + * + * @author mwood + */ +interface SearchRequestProcessor +{ + /** + * Search for Items to be mapped into a Collection. + * + * @param context + * @param query matches the interesting Items. + * @param collection into which the found Items may be mapped. + * @return found Items. + * @throws IOException + * @throws SQLException + */ + List<DSpaceObject> doItemMapSearch(Context context, String query, Collection collection) + throws IOException, SQLException; +} 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/FrontPageFeeds.java similarity index 67% rename from dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/FrontPageSearch.java rename to dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/FrontPageFeeds.java index e1c1378d2bcf03f8175b8b01487366b6666f1150..1c0c3f2489e6658dcf106ba58230f84377232085 100644 --- 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/FrontPageFeeds.java @@ -18,35 +18,24 @@ 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. + * This simple component will add feed links. It is intended for use on the front + * page. * * @author Scott Phillips */ -public class FrontPageSearch extends AbstractDSpaceTransformer implements CacheableProcessingComponent +public class FrontPageFeeds 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. @@ -95,20 +84,4 @@ public class FrontPageSearch extends AbstractDSpaceTransformer implements Cachea } } } - - - 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/ItemRequestChangeStatusForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestChangeStatusForm.java new file mode 100644 index 0000000000000000000000000000000000000000..f7113759965118aea78df2430314dd1c726435de --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestChangeStatusForm.java @@ -0,0 +1,148 @@ +/** + * 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.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.util.HashUtil; +import org.apache.commons.lang.StringUtils; +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.HandleUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Radio; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.xml.sax.SAXException; + +/** + * Display to the user a form to request change of permissions of a item. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestChangeStatusForm extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** Language Strings */ + private static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.title"); + + private static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + private static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.trail"); + + private static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.head"); + + private static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.para1"); + + private static final Message T_name = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.name"); + + private static final Message T_email = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.email"); + + private static final Message T_name_error = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.name.error"); + + private static final Message T_email_error = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.email.error"); + + private static final Message T_changeToOpen = + message("xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.changeToOpen"); + + /** + * Generate the unique caching key. + * This key must be unique inside the space of this component. + */ + public Serializable getKey() { + + String token = parameters.getParameter("token",""); + String name = parameters.getParameter("name",""); + String email = parameters.getParameter("email",""); + Request request = ObjectModelHelper.getRequest(objectModel); + String openAccess = request.getParameter("openAccess"); + return HashUtil.hash(token+name+email+openAccess); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException + { + + Request request = ObjectModelHelper.getRequest(objectModel); + + // Build the item viewer division. + Division itemRequest = body.addInteractiveDivision("itemRequest-form", + request.getRequestURI(),Division.METHOD_POST,"primary"); + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1); + + List form = itemRequest.addList("form",List.TYPE_FORM); + + Text name = form.addItem().addText("name"); + name.setLabel(T_name); + name.setValue(parameters.getParameter("name","")); + + Text mail = form.addItem().addText("email"); + mail.setLabel(T_email); + mail.setValue(parameters.getParameter("email","")); + + if(request.getParameter("openAccess")!=null){ + if(StringUtils.isEmpty(parameters.getParameter("name", ""))){ + name.addError(T_name_error); + } + if(StringUtils.isEmpty(parameters.getParameter("email", ""))){ + mail.addError(T_email_error); + } + } + // mail.setValue(parameters.getParameter("mail","")); + form.addItem().addHidden("isSent").setValue("true"); + form.addItem().addButton("openAccess").setValue(T_changeToOpen); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestForm.java new file mode 100644 index 0000000000000000000000000000000000000000..24e0be96fc957138bd5df594674167d06dd6e5e9 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestForm.java @@ -0,0 +1,192 @@ +/** + * 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.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.util.HashUtil; +import org.apache.commons.lang.StringUtils; +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.HandleUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Radio; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.xml.sax.SAXException; + +/** + * Display to the user a simple form letting the user to request a protected item. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestForm extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** Language Strings */ + private static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestForm.title"); + + private static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + private static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestForm.trail"); + + private static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestForm.head"); + + private static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestForm.para1"); + + private static final Message T_requesterEmail = + message("xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail"); + + private static final Message T_requesterEmail_help = + message("xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail_help"); + + private static final Message T_requesterEmail_error = + message("xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail.error"); + + private static final Message T_message = + message("xmlui.ArtifactBrowser.ItemRequestForm.message"); + + private static final Message T_message_error = + message("xmlui.ArtifactBrowser.ItemRequestForm.message.error"); + + private static final Message T_requesterName = + message("xmlui.ArtifactBrowser.ItemRequestForm.requesterName"); + + private static final Message T_requesterName_error = + message("xmlui.ArtifactBrowser.ItemRequestForm.requesterName.error"); + + private static final Message T_allFiles = + message("xmlui.ArtifactBrowser.ItemRequestForm.allFiles"); + + private static final Message T_files = + message("xmlui.ArtifactBrowser.ItemRequestForm.files"); + + private static final Message T_notAllFiles = + message("xmlui.ArtifactBrowser.ItemRequestForm.notAllFiles"); + + private static final Message T_submit = + message("xmlui.ArtifactBrowser.ItemRequestForm.submit"); + + /** + * Generate the unique caching key. + * This key must be unique inside the space of this component. + */ + public Serializable getKey() { + + String requesterName = parameters.getParameter("requesterName",""); + String requesterEmail = parameters.getParameter("requesterEmail",""); + String allFiles = parameters.getParameter("allFiles",""); + String message = parameters.getParameter("message",""); + String bitstreamId = parameters.getParameter("bitstreamId",""); + + return HashUtil.hash(requesterName + "-" + requesterEmail + "-" + allFiles +"-"+message+"-"+bitstreamId); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException { + + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); + if (!(dso instanceof Item)) { + return; + } + Request request = ObjectModelHelper.getRequest(objectModel); + boolean firstVisit=Boolean.valueOf(request.getParameter("firstVisit")); + + Item item = (Item) dso; + // Build the item viewer division. + Division itemRequest = body.addInteractiveDivision("itemRequest-form", + request.getRequestURI(), Division.METHOD_POST, "primary"); + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1); + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null && titleDC.length > 0) + itemRequest.addPara(titleDC[0].value); + + List form = itemRequest.addList("form", List.TYPE_FORM); + + Text requesterName = form.addItem().addText("requesterName"); + requesterName.setLabel(T_requesterName); + requesterName.setValue(parameters.getParameter("requesterName", "")); + + Text requesterEmail = form.addItem().addText("requesterEmail"); + requesterEmail.setLabel(T_requesterEmail); + requesterEmail.setHelp(T_requesterEmail_help); + requesterEmail.setValue(parameters.getParameter("requesterEmail", "")); + + Radio radio = form.addItem().addRadio("allFiles"); + String selected=!parameters.getParameter("allFiles","true").equalsIgnoreCase("false")?"true":"false"; + radio.setOptionSelected(selected); + radio.setLabel(T_files); + radio.addOption("true", T_allFiles); + radio.addOption("false", T_notAllFiles); + + + TextArea message = form.addItem().addTextArea("message"); + message.setLabel(T_message); + message.setValue(parameters.getParameter("message", "")); + form.addItem().addHidden("bitstreamId").setValue(parameters.getParameter("bitstreamId", "")); + form.addItem().addButton("submit").setValue(T_submit); + + // if button is pressed and form is re-loaded it means some parameter is missing + if(request.getParameter("submit")!=null){ + if(StringUtils.isEmpty(parameters.getParameter("requesterName", ""))){ + requesterName.addError(T_requesterName_error); + } + if(StringUtils.isEmpty(parameters.getParameter("requesterEmail", ""))){ + requesterEmail.addError(T_requesterEmail_error); + } + if(StringUtils.isEmpty(parameters.getParameter("message", ""))){ + message.addError(T_message_error); + } + } + itemRequest.addHidden("page").setValue(parameters.getParameter("page", "unknown")); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseAction.java new file mode 100644 index 0000000000000000000000000000000000000000..2873b99aab9cc78e8ca4a138f79a8171ae66d652 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseAction.java @@ -0,0 +1,202 @@ +/** + * 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.net.InetAddress; +import java.sql.SQLException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import javax.mail.MessagingException; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.acting.AbstractAction; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.xmlui.utils.ContextUtil; +import org.dspace.app.xmlui.utils.HandleUtil; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.core.Email; +import org.dspace.core.I18nUtil; +import org.dspace.core.LogManager; +import org.dspace.core.Utils; +import org.dspace.eperson.EPerson; +import org.dspace.handle.HandleManager; +import org.dspace.storage.bitstore.BitstreamStorageManager; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; + + +/** + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestResponseAction extends AbstractAction +{ + /** log4j log */ + private static Logger log = Logger.getLogger(ItemRequestResponseAction.class); + + public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, + String source, Parameters parameters) throws Exception + { + Request request = ObjectModelHelper.getRequest(objectModel); + + String token = parameters.getParameter("token",""); + String decision = request.getParameter("decision"); + String isSent = request.getParameter("isSent"); + String message = request.getParameter("message"); + Context context = ContextUtil.obtainContext(objectModel); + request.setAttribute("token", token); + + TableRow requestItem = DatabaseManager.findByUnique(context, "requestitem", "token", token); + String title; + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) + title=titleDC[0].value; + else + title="untitled"; + + String button=""; + // Botones de las paginas: + if(request.getParameter("send")!=null){ + decision="true"; + button="send"; + }else if(request.getParameter("dontSend")!=null){ + decision="false"; + button="dontSend"; + } + if(request.getParameter("mail")!=null){ + button="mail"; + }else if(request.getParameter("back")!=null){ + button="back"; + } + if(request.getParameter("openAccess")!=null){ + button="openAccess"; + } + + if(button.equals("mail")&& StringUtils.isNotEmpty(decision) && decision.equals("true")){ + processSendDocuments(context,request,requestItem,item,title); + isSent="true"; + }else if(button.equals("mail")&& StringUtils.isNotEmpty(decision) && decision.equals("false")){ + processDeny(context,request,requestItem,item,title); + isSent="true"; + }else if(button.equals("openAccess")){ + if(processOpenAccessRequest(context,request,requestItem,item,title)){ + // se acabo el flujo + return null; + } + }else if(button.equals("back")){ + decision=null; + } + + + Map<String, String> map = new HashMap<String, String>(); + map.put("decision", decision); + map.put("token", token); + map.put("isSent", isSent); + map.put("title", title); + map.put("name", request.getParameter("name")); + map.put("email",request.getParameter("email")); + return map; + } + + + + private boolean processOpenAccessRequest(Context context,Request request, TableRow requestItem,Item item,String title) throws SQLException, IOException, MessagingException { + String name = request.getParameter("name"); + String mail = request.getParameter("email"); + if(StringUtils.isNotEmpty(name)&&StringUtils.isNotEmpty(mail)){ + String emailRequest; + EPerson submiter = item.getSubmitter(); + if(submiter!=null){ + emailRequest=submiter.getEmail(); + }else{ + emailRequest=ConfigurationManager.getProperty("mail.helpdesk"); + } + if(emailRequest==null){ + emailRequest=ConfigurationManager.getProperty("mail.admin"); + } + Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "request_item.admin")); + email.addRecipient(emailRequest); + + email.addArgument(Bitstream.find(context,requestItem.getIntColumn("bitstream_id")).getName()); + email.addArgument(HandleManager.getCanonicalForm(item.getHandle())); + email.addArgument(requestItem.getStringColumn("token")); + email.addArgument(name); + email.addArgument(mail); + + email.send(); + return true; + } + return false; + } + + private void processSendDocuments(Context context,Request request, TableRow requestItem,Item item,String title) throws SQLException, MessagingException, IOException { + String message = request.getParameter("message"); + String subject = request.getParameter("subject"); + + Email email = new Email(); + email.setSubject(subject); + email.setContent("{0}"); + email.addRecipient(requestItem.getStringColumn("request_email")); + email.addArgument(message); + + if (requestItem.getBooleanColumn("allfiles")){ + Bundle[] bundles = item.getBundles("ORIGINAL"); + for (int i = 0; i < bundles.length; i++){ + Bitstream[] bitstreams = bundles[i].getBitstreams(); + for (int k = 0; k < bitstreams.length; k++){ + if (!bitstreams[k].getFormat().isInternal() /*&& RequestItemManager.isRestricted(context, bitstreams[k])*/){ + email.addAttachment(BitstreamStorageManager.retrieve(context, bitstreams[k].getID()), bitstreams[k].getName(), bitstreams[k].getFormat().getMIMEType()); + } + } + } + } else { + Bitstream bit = Bitstream.find(context,requestItem.getIntColumn("bitstream_id")); + email.addAttachment(BitstreamStorageManager.retrieve(context, requestItem.getIntColumn("bitstream_id")), bit.getName(), bit.getFormat().getMIMEType()); + } + + email.send(); + requestItem.setColumn("decision_date",new Date()); + requestItem.setColumn("accept_request",true); + DatabaseManager.update(context, requestItem); + } + + private void processDeny(Context context,Request request, TableRow requestItem,Item item,String title) throws SQLException, IOException, MessagingException { + String message = request.getParameter("message"); + String subject = request.getParameter("subject"); + + Email email = new Email(); + email.setSubject(subject); + email.setContent("{0}"); + email.addRecipient(requestItem.getStringColumn("request_email")); + email.addArgument(message); + email.send(); + + requestItem.setColumn("decision_date",new Date()); + requestItem.setColumn("accept_request",false); + DatabaseManager.update(context, requestItem); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseDecisionForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseDecisionForm.java new file mode 100644 index 0000000000000000000000000000000000000000..6dfa3215b43dcaad9a14031bc495bf5814bc839b --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseDecisionForm.java @@ -0,0 +1,112 @@ +/** + * 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.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.xmlui.cocoon.AbstractDSpaceTransformer; +import org.dspace.app.xmlui.utils.HandleUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Para; +import org.dspace.app.xmlui.wing.element.Radio; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.xml.sax.SAXException; + +/** + * Display to the user a simple decision form to select sending or not a file to + * requester. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestResponseDecisionForm extends AbstractDSpaceTransformer + implements CacheableProcessingComponent { + /** Language Strings */ + private static final Message T_title = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.title"); + + private static final Message T_dspace_home = message("xmlui.general.dspace_home"); + + private static final Message T_trail = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.trail"); + + private static final Message T_head = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.head"); + + private static final Message T_para1 = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.para1"); + + private static final Message T_para2 = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.para2"); + + private static final Message T_send = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.send"); + + private static final Message T_dontSend = message("xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.dontSend"); + + /** + * Generate the unique caching key. This key must be unique inside the space + * of this component. + */ + public Serializable getKey() { + + String title = parameters.getParameter("title",""); + return HashUtil.hash(title); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() { + return NOPValidity.SHARED_INSTANCE; + } + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/", T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException { + + Request request = ObjectModelHelper.getRequest(objectModel); + String title = parameters.getParameter("title",""); + // Build the item viewer division. + Division itemRequest = body.addInteractiveDivision("itemRequest-form", + request.getRequestURI(), Division.METHOD_POST, "primary"); + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1.parameterize(title)); + itemRequest.addPara(T_para2); + + List form = itemRequest.addList("form", List.TYPE_FORM); + + form.addItem().addButton("send").setValue(T_send); + form.addItem().addButton("dontSend").setValue(T_dontSend); + + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseFalseForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseFalseForm.java new file mode 100644 index 0000000000000000000000000000000000000000..ce1f56f0d7e8361e93d0c0edab831c03f7ed21a8 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseFalseForm.java @@ -0,0 +1,162 @@ +/** + * 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 java.text.MessageFormat; + +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.xmlui.cocoon.AbstractDSpaceTransformer; +import org.dspace.app.xmlui.utils.ContextUtil; +import org.dspace.app.xmlui.utils.HandleUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Radio; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.core.I18nUtil; +import org.dspace.eperson.EPerson; +import org.dspace.handle.HandleManager; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.xml.sax.SAXException; + +/** + * Display to the user a simple form to send a message rejecting the file send. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestResponseFalseForm extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** Language Strings */ + private static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.title"); + + private static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + private static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.trail"); + + private static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.head"); + + private static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.para1"); + + private static final Message T_mail = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.mail"); + + private static final Message T_back = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.back"); + + private static final Message T_message = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.message"); + + private static final Message T_subject = + message("xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.subject"); + /** + * Generate the unique caching key. + * This key must be unique inside the space of this component. + */ + public Serializable getKey() { + + String token = parameters.getParameter("token", ""); + String decision = parameters.getParameter("decision", ""); + + return HashUtil.hash(token+"-"+decision); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException + { + Request request = ObjectModelHelper.getRequest(objectModel); + Context context = ContextUtil.obtainContext(objectModel); + + TableRow requestItem = DatabaseManager.findByUnique(context, + "requestitem", "token", (String) request.getAttribute("token")); + String title; + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) + title = titleDC[0].value; + else + title = "untitled"; + + EPerson submitter = item.getSubmitter(); + + Object[] args = new String[]{ + requestItem.getStringColumn("request_name"), + HandleManager.getCanonicalForm(item.getHandle()), // User + title, // request item title + submitter.getFullName(), // # submmiter name + submitter.getEmail() // # submmiter email + }; + + String subject = I18nUtil.getMessage("itemRequest.response.subject.reject", context); + String messageTemplate = MessageFormat.format(I18nUtil.getMessage("itemRequest.response.body.reject", context), args); + + Division itemRequest = body.addInteractiveDivision("itemRequest-form", + request.getRequestURI(),Division.METHOD_POST,"primary"); + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1); + + List form = itemRequest.addList("form",List.TYPE_FORM); + + Text subj = form.addItem().addText("subject"); + subj.setLabel(T_subject); + subj.setValue(subject); + subj.setSize(60); + TextArea message = form.addItem().addTextArea("message"); + message.setSize(20, 0); + message.setLabel(T_message); + message.setValue(parameters.getParameter("message",messageTemplate)); + form.addItem().addHidden("decision").setValue(parameters.getParameter("decision","")); + form.addItem().addButton("back").setValue(T_back); + form.addItem().addButton("mail").setValue(T_mail); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseTrueForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseTrueForm.java new file mode 100644 index 0000000000000000000000000000000000000000..e53d820a1145abe0cca9059481a6c82eb7cbecfb --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestResponseTrueForm.java @@ -0,0 +1,157 @@ +/** + * 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 java.text.MessageFormat; + +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.xmlui.cocoon.AbstractDSpaceTransformer; +import org.dspace.app.xmlui.utils.ContextUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.Item; +import org.dspace.core.Context; +import org.dspace.core.I18nUtil; +import org.dspace.eperson.EPerson; +import org.dspace.handle.HandleManager; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.xml.sax.SAXException; + +/** + * Display to the user a simple form letting the user send a document with a message. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestResponseTrueForm extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** Language Strings */ + private static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.title"); + + private static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + private static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.trail"); + + private static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.head"); + + private static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.para1"); + + private static final Message T_mail = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.mail"); + + private static final Message T_back = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.back"); + + private static final Message T_message = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.message"); + + private static final Message T_subject = + message("xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.subject"); + + /** + * Generate the unique caching key. + * This key must be unique inside the space of this component. + */ + public Serializable getKey() { + String token = parameters.getParameter("token", ""); + String decision = parameters.getParameter("decision", ""); + + return HashUtil.hash(token+"-"+decision); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException + { + Request request = ObjectModelHelper.getRequest(objectModel); + Context context = ContextUtil.obtainContext(objectModel); + + TableRow requestItem = DatabaseManager.findByUnique(context, + "requestitem", "token", (String) request.getAttribute("token")); + String title; + Item item = Item.find(context, requestItem.getIntColumn("item_id")); + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) + title = titleDC[0].value; + else + title = "untitled"; + + EPerson submitter = item.getSubmitter(); + + Object[] args = new String[]{ + requestItem.getStringColumn("request_name"), + HandleManager.getCanonicalForm(item.getHandle()), // User + title, // request item title + submitter.getFullName(), // # submmiter name + submitter.getEmail() // # submmiter email + }; + + String subject = I18nUtil.getMessage("itemRequest.response.subject.approve", context); + String messageTemplate = MessageFormat.format(I18nUtil.getMessage("itemRequest.response.body.approve", context), args); + + Division itemRequest = body.addInteractiveDivision("itemRequest-form", request.getRequestURI(),Division.METHOD_POST,"primary"); + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1); + + List form = itemRequest.addList("form",List.TYPE_FORM); + Text subj = form.addItem().addText("subject"); + subj.setLabel(T_subject); + subj.setValue(subject); + subj.setSize(60); + TextArea message = form.addItem().addTextArea("message"); + message.setSize(20, 0); + message.setLabel(T_message); + message.setValue(parameters.getParameter("message",messageTemplate)); + form.addItem().addHidden("decision").setValue(parameters.getParameter("decision","")); + form.addItem().addButton("back").setValue(T_back); + form.addItem().addButton("mail").setValue(T_mail); + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestSent.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestSent.java new file mode 100644 index 0000000000000000000000000000000000000000..55c5989a2012e21c068e5af01d3d1dcf1895175a --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestSent.java @@ -0,0 +1,91 @@ +/** + * 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.authorize.AuthorizeException; +import org.xml.sax.SAXException; + +/** + * Simple page to let the user know their mail and file has been sent. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestSent extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** language strings */ + public static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestSent.title"); + + public static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + public static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestSent.trail"); + + public static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestSent.head"); + + public static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestSent.para1"); + + /** + * Generate the unique caching key. + */ + public Serializable getKey() { + return 0; + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException + { + Division feedback = body.addDivision("itemRequest-sent","primary"); + + feedback.setHead(T_head); + + feedback.addPara(T_para1); + + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestStatusChanged.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestStatusChanged.java new file mode 100644 index 0000000000000000000000000000000000000000..6d106c1711f428253097c2eaae9b28e188e3ca84 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/ItemRequestStatusChanged.java @@ -0,0 +1,107 @@ +/** + * 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.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.xmlui.cocoon.AbstractDSpaceTransformer; +import org.dspace.app.xmlui.utils.HandleUtil; +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.List; +import org.dspace.app.xmlui.wing.element.PageMeta; +import org.dspace.app.xmlui.wing.element.Radio; +import org.dspace.app.xmlui.wing.element.Text; +import org.dspace.app.xmlui.wing.element.TextArea; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.xml.sax.SAXException; + +/** + * Display to the user a simple page to let the user know the mail to request change status of a item is sent. + * + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class ItemRequestStatusChanged extends AbstractDSpaceTransformer implements CacheableProcessingComponent +{ + /** Language Strings */ + private static final Message T_title = + message("xmlui.ArtifactBrowser.ItemRequestStatusChanged.title"); + + private static final Message T_dspace_home = + message("xmlui.general.dspace_home"); + + private static final Message T_trail = + message("xmlui.ArtifactBrowser.ItemRequestStatusChanged.trail"); + + private static final Message T_head = + message("xmlui.ArtifactBrowser.ItemRequestStatusChanged.head"); + + private static final Message T_para1 = + message("xmlui.ArtifactBrowser.ItemRequestStatusChanged.para1"); + + private static final Message T_para2 = + message("xmlui.ArtifactBrowser.ItemRequestStatusChanged.para2"); + + /** + * Generate the unique caching key. + * This key must be unique inside the space of this component. + */ + public Serializable getKey() { + + String token = parameters.getParameter("token", ""); + return HashUtil.hash(token); + } + + /** + * Generate the cache validity object. + */ + public SourceValidity getValidity() + { + return NOPValidity.SHARED_INSTANCE; + } + + + public void addPageMeta(PageMeta pageMeta) throws SAXException, + WingException, UIException, SQLException, IOException, + AuthorizeException + { + pageMeta.addMetadata("title").addContent(T_title); + + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + pageMeta.addTrail().addContent(T_trail); + } + + public void addBody(Body body) throws SAXException, WingException, + UIException, SQLException, IOException, AuthorizeException + { + Division itemRequest = body.addDivision("itemRequestStatus"); + + itemRequest.setHead(T_head); + + itemRequest.addPara(T_para1); + itemRequest.addPara(T_para2); + } +} 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/SendItemRequestAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendItemRequestAction.java new file mode 100644 index 0000000000000000000000000000000000000000..5133bc3994e9658513e95cccdfd410096db1c4ec --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendItemRequestAction.java @@ -0,0 +1,210 @@ +/** + * 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.sql.SQLException; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.acting.AbstractAction; +import org.apache.cocoon.environment.ObjectModelHelper; +import org.apache.cocoon.environment.Redirector; +import org.apache.cocoon.environment.Request; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.dspace.app.requestitem.RequestItemAuthor; +import org.dspace.app.requestitem.RequestItemAuthorExtractor; +import org.dspace.app.xmlui.utils.ContextUtil; +import org.dspace.app.xmlui.utils.HandleUtil; +import org.dspace.content.Bitstream; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.core.Email; +import org.dspace.core.I18nUtil; +import org.dspace.core.Utils; +import org.dspace.eperson.EPerson; +import org.dspace.handle.HandleManager; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.dspace.utils.DSpace; + + /** + * This action will send a mail to request a item to administrator when all mandatory data is present. + * It will record the request into the database. + * + * 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 Adán Román Ruiz at arvo.es (added request item support) + */ +public class SendItemRequestAction extends AbstractAction +{ + private static Logger log = Logger.getLogger(SendItemRequestAction.class); + + public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, + String source, Parameters parameters) throws Exception + { + Request request = ObjectModelHelper.getRequest(objectModel); + + String requesterName = request.getParameter("requesterName"); + String requesterEmail = request.getParameter("requesterEmail"); + String allFiles = request.getParameter("allFiles"); + String message = request.getParameter("message"); + String bitstreamId = request.getParameter("bitstreamId"); + + // User email from context + Context context = ContextUtil.obtainContext(objectModel); + EPerson loggedin = context.getCurrentUser(); + String eperson = null; + if (loggedin != null) + { + eperson = loggedin.getEmail(); + } + + // Check all data is there + if (StringUtils.isEmpty(requesterName) || StringUtils.isEmpty(requesterEmail) || StringUtils.isEmpty(allFiles) || StringUtils.isEmpty(message)) + { + // Either the user did not fill out the form or this is the + // first time they are visiting the page. + Map<String,String> map = new HashMap<String,String>(); + map.put("bitstreamId",bitstreamId); + + if (StringUtils.isEmpty(requesterEmail)) + { + map.put("requesterEmail", eperson); + } + else + { + map.put("requesterEmail", requesterEmail); + } + map.put("requesterName",requesterName); + map.put("allFiles",allFiles); + map.put("message",message); + return map; + } + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); + if (!(dso instanceof Item)) + { + throw new Exception("Invalid DspaceObject at ItemRequest."); + } + + Item item = (Item) dso; + String title=""; + DCValue[] titleDC = item.getDC("title", null, Item.ANY); + if (titleDC != null || titleDC.length > 0) { + title=titleDC[0].value; + } + String emailRequest; + + RequestItemAuthor author = new DSpace() + .getServiceManager() + .getServiceByName(RequestItemAuthorExtractor.class.getName(), + RequestItemAuthorExtractor.class) + .getRequestItemAuthor(context, item); + + String authorEmail = author.getEmail(); + String authorName = author.getFullName(); + + if(authorEmail!=null){ + emailRequest=authorEmail; + }else{ + emailRequest=ConfigurationManager.getProperty("mail.helpdesk"); + } + if(emailRequest==null){ + emailRequest=ConfigurationManager.getProperty("mail.admin"); + } + // All data is there, send the email + Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "request_item.author")); + email.addRecipient(emailRequest); + + email.addArgument(requesterName); + email.addArgument(requesterEmail); + email.addArgument(allFiles.equals("true")?I18nUtil.getMessage("itemRequest.all"):Bitstream.find(context,Integer.parseInt(bitstreamId)).getName()); + email.addArgument(HandleManager.getCanonicalForm(item.getHandle())); + email.addArgument(title); // request item title + email.addArgument(message); // message + email.addArgument(getLinkTokenEmail(context,request, bitstreamId, item.getID(), requesterEmail, requesterName, Boolean.parseBoolean(allFiles))); + email.addArgument(authorName); // corresponding author name + email.addArgument(authorEmail); // corresponding author email + email.addArgument(ConfigurationManager.getProperty("dspace.name")); + email.addArgument(ConfigurationManager.getProperty("mail.helpdesk")); + + email.setReplyTo(requesterEmail); + + email.send(); + // Finished, allow to pass. + return null; + } + + /** + * Get the link to the author in RequestLink email. + * + * @param email + * The email address to mail to + * + * @exception SQLExeption + * + */ + protected String getLinkTokenEmail(Context context,Request request, String bitstreamId + , int itemID, String reqEmail, String reqName, boolean allfiles) + throws SQLException + { + String base = ConfigurationManager.getProperty("dspace.url"); + + request.getPathInfo(); + String specialLink = (new StringBuffer()).append(base).append( + base.endsWith("/") ? "" : "/").append( + "itemRequestResponse/").append(getNewToken(context, Integer.parseInt(bitstreamId), itemID, reqEmail, reqName, allfiles)) + .toString()+"/"; + + return specialLink; + } + /** + * Generate a unique id of the request and put it into the ddbb + * @param context + * @param bitstreamId + * @param itemID + * @param reqEmail + * @param reqName + * @param allfiles + * @return + * @throws SQLException + */ + protected String getNewToken(Context context, int bitstreamId, int itemID, String reqEmail, String reqName, boolean allfiles) throws SQLException + { + TableRow rd = DatabaseManager.create(context, "requestitem"); + rd.setColumn("token", Utils.generateHexKey()); + rd.setColumn("bitstream_id", bitstreamId); + rd.setColumn("item_id",itemID); + rd.setColumn("allfiles", allfiles); + rd.setColumn("request_email", reqEmail); + rd.setColumn("request_name", reqName); + rd.setColumnNull("accept_request"); + rd.setColumn("request_date", new Date()); + rd.setColumnNull("decision_date"); + rd.setColumnNull("expires"); + + DatabaseManager.update(context, rd); + + if (log.isDebugEnabled()) + { + log.debug("Created requestitem_token " + + rd.getIntColumn("requestitem_id") + + " with token " + rd.getStringColumn("token") + + "\""); + } + return rd.getStringColumn("token"); + + } +} 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/CollectionBrowse.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/CollectionBrowse.java new file mode 100644 index 0000000000000000000000000000000000000000..bc76e561c8e6cb5a513667c8783bd9166dcae146 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/CollectionBrowse.java @@ -0,0 +1,93 @@ +/** + * 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.browseArtifacts; + +import org.apache.cocoon.ProcessingException; +import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; +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.Body; +import org.dspace.app.xmlui.wing.element.Division; +import org.dspace.app.xmlui.wing.element.List; +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.xml.sax.SAXException; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +/** + * Renders the browse links for a collection + * + * @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 CollectionBrowse extends AbstractDSpaceTransformer { + + 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"); + + @Override + public void addBody(Body body) throws SAXException, WingException, SQLException, IOException, AuthorizeException, ProcessingException { + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); + if (!(dso instanceof Collection)) + { + return; + } + + // Set up the major variables + Collection collection = (Collection) dso; + + Division home = body.addDivision("collection-home", "primary repository collection"); + + Division search = 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(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); + } + } +} \ No newline at end of file diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/CommunityBrowse.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/CommunityBrowse.java new file mode 100644 index 0000000000000000000000000000000000000000..04b3a0110415459888dcbbee44522c566d54cfe6 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/CommunityBrowse.java @@ -0,0 +1,93 @@ +/** + * 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.browseArtifacts; + +import org.apache.cocoon.ProcessingException; +import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; +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.Body; +import org.dspace.app.xmlui.wing.element.Division; +import org.dspace.app.xmlui.wing.element.List; +import org.dspace.authorize.AuthorizeException; +import org.dspace.browse.BrowseException; +import org.dspace.browse.BrowseIndex; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +/** + * Renders the browse links for a community + * + * @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 CommunityBrowse extends AbstractDSpaceTransformer { + + 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"); + + @Override + public void addBody(Body body) throws SAXException, WingException, SQLException, IOException, AuthorizeException, ProcessingException { + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); + if (!(dso instanceof Community)) + { + return; + } + + // Set up the major variables + Community community = (Community) dso; + + Division home = body.addDivision("community-home", "primary repository community"); + + Division search = home.addDivision("community-search-browse", + "secondary search-browse"); + + // 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(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); + } + } +} \ No newline at end of file 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/discovery/recentSubmissions/RecentSubmissionTransformer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/recentSubmissions/RecentSubmissionTransformer.java new file mode 100644 index 0000000000000000000000000000000000000000..5e876a8e6171351f225ef2ea219554c7bd154f5d --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/recentSubmissions/RecentSubmissionTransformer.java @@ -0,0 +1,210 @@ +/** + * 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.discovery.recentSubmissions; + +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.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.Message; +import org.dspace.app.xmlui.wing.WingException; +import org.dspace.app.xmlui.wing.element.*; +import org.dspace.authorize.AuthorizeException; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Site; +import org.dspace.core.ConfigurationManager; +import org.dspace.discovery.DiscoverResult; +import org.xml.sax.SAXException; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Map; + +/** + * Transformer that renders recent submissions with a paging option to traverse them + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class RecentSubmissionTransformer extends AbstractDSpaceTransformer { + + protected static final Message T_dspace_home = message("xmlui.general.dspace_home"); + protected static final Message T_untitled = message("xmlui.general.untitled"); + protected static final Message T_head = message("xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.head"); + protected static final Message T_recent_submission_head = message("xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.recent.head"); + protected static final Message T_trail = message("xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.trail"); + + protected boolean isHomePage = false; + + @Override + public void setup(SourceResolver resolver, Map objectModel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { + super.setup(resolver, objectModel, src, parameters); + isHomePage = parameters.getParameterAsBoolean("isHomePage", false); + } + + @Override + public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException { + DSpaceObject dso = getDSpaceObject(); + + // Set up the major variables + // Set the page title + String name = dso.getName(); + Metadata titlePageMeta = pageMeta.addMetadata("title"); + if (name == null || name.length() == 0) + { + if(isHomePage){ + titlePageMeta.addContent(T_untitled); + }else{ + titlePageMeta.addContent(T_recent_submission_head.parameterize(name)); + } + } + else + { + if(isHomePage){ + titlePageMeta.addContent(name); + }else{ + titlePageMeta.addContent(T_recent_submission_head.parameterize(name)); + } + } + + // Add the trail back to the repository root. + pageMeta.addTrailLink(contextPath + "/",T_dspace_home); + HandleUtil.buildHandleTrail(dso, pageMeta,contextPath, !isHomePage); + if(!isHomePage) + { + //Add a trail link indicating that we are on a recent submissions page + pageMeta.addTrail().addContent(T_trail); + } + + /** + * If we are on a home page add the feeds (if enabled) + */ + if(isHomePage) + { + // 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()+"/"+dso.getHandle(); + pageMeta.addMetadata("feed", feedFormat).addContent(feedURL); + } + } + } + } + + @Override + public void addBody(Body body) throws SAXException, WingException, SQLException, IOException, AuthorizeException, ProcessingException { + Request request = ObjectModelHelper.getRequest(objectModel); + DSpaceObject dso = getDSpaceObject(); + + Division mainDivision = body.addDivision("main-recent-submissions"); + setMainTitle(dso, mainDivision); + Division recentSubmissionDivision = mainDivision.addDivision("recent-submissions"); + if(isHomePage){ + recentSubmissionDivision.setHead(T_recent_submission_head); + } + + DiscoverResult recentlySubmittedItems = RecentSubmissionUtils.getRecentlySubmittedItems(context, dso, getOffset(request)); + setPagination(request, dso, recentSubmissionDivision, recentlySubmittedItems); + + ReferenceSet lastSubmitted = recentSubmissionDivision.addReferenceSet( + "last-submitted", ReferenceSet.TYPE_SUMMARY_LIST, + null, "recent-submissions"); + + for (DSpaceObject resultObject : recentlySubmittedItems.getDspaceObjects()) { + if(resultObject != null){ + lastSubmitted.addReference(resultObject); + } + } + } + + protected void setPagination(Request request, DSpaceObject dso, Division mainDivision, DiscoverResult recentlySubmittedItems) { + int offset = getOffset(request); + int rpp = RecentSubmissionUtils.getRecentSubmissionConfiguration(dso).getMax(); + int firstIndex = offset + 1; + int lastIndex = offset + recentlySubmittedItems.getDspaceObjects().size(); + mainDivision.setSimplePagination((int) recentlySubmittedItems.getTotalSearchResults(), firstIndex, + lastIndex, getPreviousPageURL(dso, offset, rpp), getNextPageURL(dso, offset, rpp, (int) recentlySubmittedItems.getTotalSearchResults())); + } + + protected void setMainTitle(DSpaceObject dso, Division mainDivision) throws WingException { + String title = dso.getName(); + if(isHomePage) + { + mainDivision.setHead(title); + }else{ + //We are not acting as home page so use a message + mainDivision.setHead(T_head.parameterize(title)); + } + + } + + protected String getNextPageURL(DSpaceObject dso, int currentOffset, int rpp, int total){ + if((rpp + currentOffset) < total) + { + return getBaseUrl(dso) + "?offset=" + (rpp + currentOffset); + }else{ + return null; + } + } + + protected String getPreviousPageURL(DSpaceObject dso, int currentOffset, int rpp) { + if((currentOffset - rpp) < 0){ + return null; + }else{ + return getBaseUrl(dso) + "?offset=" + (currentOffset - rpp); + } + } + + protected String getBaseUrl(DSpaceObject dso) + { + String url = contextPath; + if(dso != null && dso.getID() != Site.SITE_ID) + { + url += "/handle/" + dso.getHandle(); + } + if(!isHomePage) + { + url += "/recent-submissions"; + } + return url; + } + + protected int getOffset(Request request) { + int start = Util.getIntParameter(request, "offset"); + if(start == -1){ + start = 0; + } + return start; + } + + protected DSpaceObject getDSpaceObject() throws SQLException { + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); + if(dso == null) + { + return Site.find(context, Site.SITE_ID); + }else{ + return dso; + } + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/recentSubmissions/RecentSubmissionUtils.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/recentSubmissions/RecentSubmissionUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..701af85c7d2dbe9767436e75d5231b97f6517304 --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/recentSubmissions/RecentSubmissionUtils.java @@ -0,0 +1,79 @@ +/** + * 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.discovery.recentSubmissions; + +import org.apache.log4j.Logger; +import org.dspace.content.DSpaceObject; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.discovery.*; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration; + +import java.util.List; + +/** + * Class containing utility methods used to render recent submissions + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class RecentSubmissionUtils { + + private static final Logger log = Logger.getLogger(RecentSubmissionUtils.class); + + /** + * Retrieves the recent submitted items of the given scope + * + * @param dso the DSpace object can either be null (indicating home page), a collection or a community + */ + public static DiscoverResult getRecentlySubmittedItems(Context context, DSpaceObject dso, int offset) { + try { + DiscoverQuery queryArgs = new DiscoverQuery(); + + //Add the default filter queries + DiscoveryConfiguration discoveryConfiguration = getDiscoveryConfiguration(dso); + List<String> defaultFilterQueries = discoveryConfiguration.getDefaultFilterQueries(); + queryArgs.addFilterQueries(defaultFilterQueries.toArray(new String[defaultFilterQueries.size()])); + queryArgs.setDSpaceObjectFilter(Constants.ITEM); + + DiscoveryRecentSubmissionsConfiguration recentSubmissionConfiguration = getRecentSubmissionConfiguration(discoveryConfiguration); + if(recentSubmissionConfiguration != null){ + queryArgs.setMaxResults(recentSubmissionConfiguration.getMax()); + queryArgs.setStart(offset); + String sortField = SearchUtils.getSearchService().toSortFieldIndex(recentSubmissionConfiguration.getMetadataSortField(), recentSubmissionConfiguration.getType()); + if(sortField != null){ + queryArgs.setSortField( + sortField, + DiscoverQuery.SORT_ORDER.desc + ); + } + SearchService service = SearchUtils.getSearchService(); + return service.search(context, dso, queryArgs); + }else{ + //No configuration, no results + return null; + } + }catch (SearchServiceException se){ + log.error("Caught SearchServiceException while retrieving recent submission for: " + (dso == null ? "home page" : dso.getHandle()), se); + return null; + } + } + + public static DiscoveryRecentSubmissionsConfiguration getRecentSubmissionConfiguration(DSpaceObject dso) { + return getRecentSubmissionConfiguration(getDiscoveryConfiguration(dso)); + + } + public static DiscoveryRecentSubmissionsConfiguration getRecentSubmissionConfiguration(DiscoveryConfiguration discoveryConfiguration) { + return discoveryConfiguration.getRecentSubmissionConfiguration(); + } + + public static DiscoveryConfiguration getDiscoveryConfiguration(DSpaceObject dso) { + return SearchUtils.getDiscoveryConfiguration(dso); + } + +} 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/general/ConfigurationMatcher.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/general/ConfigurationMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..11b68fe6799f280e17c7e1c09ddf319c00b89ccc --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/general/ConfigurationMatcher.java @@ -0,0 +1,87 @@ +/** + * 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.general; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.avalon.framework.logger.AbstractLogEnabled; +import org.apache.avalon.framework.parameters.Parameters; +import org.apache.cocoon.matching.Matcher; +import org.apache.cocoon.sitemap.PatternException; +import org.apache.cocoon.util.ConfigurationUtil; +import org.apache.commons.lang.StringUtils; +import org.dspace.app.xmlui.utils.ContextUtil; +import org.dspace.app.xmlui.utils.HandleUtil; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.content.DSpaceObject; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; + +/** + * Use the configuration in Dspace.cfg to select paths in sitemap.xmap + * + * 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 Adán Román Ruiz at arvo.es + */ + +public class ConfigurationMatcher extends AbstractLogEnabled implements Matcher +{ + /** + * Format "keyInDspace.cfg,value,value" + * "Only property" check if it is defined(not empty), + * "property,value" check if property has this value, + * "property, value,value..." check that property has one of the following values. + * operator ! is alowed: "!property, value, value2" property has not value 1 nor value 2 + * @param pattern + * name of sitemap parameter to find + * @param objectModel + * environment passed through via cocoon + * @return null or map containing value of sitemap parameter 'pattern' + */ + public Map match(String pattern, Map objectModel, Parameters parameters) throws PatternException + { + boolean not = false; + boolean itMatch = false; + if (pattern.startsWith("!")) { + not = true; + pattern = pattern.substring(1); + } + String[] expressions = pattern.split(","); + String propertyValue = ConfigurationManager.getProperty(expressions[0]); + if (expressions.length == 1) { + if (StringUtils.isNotEmpty(propertyValue)) { + itMatch = true; + } else { + itMatch = false; + } + } else { + for (int i = 1; i < expressions.length; i++) { + if (StringUtils.equalsIgnoreCase(expressions[i], propertyValue)) { + itMatch = true; + break; + } + } + itMatch = false; + } + if (itMatch && !not) { + return new HashMap(); + } else if (itMatch && not) { + return null; + } else if (!itMatch && !not) { + return null; + } else if (!itMatch && not) { + return new HashMap(); + } + return null; + } +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/handle/HandleResolverReader.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/handle/HandleResolverReader.java new file mode 100644 index 0000000000000000000000000000000000000000..3b0cb6540b0a0c9ee7afde37a413e2f5a216bf9f --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/handle/HandleResolverReader.java @@ -0,0 +1,162 @@ +/** + * 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.handle; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson.Gson; + +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.apache.avalon.excalibur.pool.Recyclable; +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.Response; +import org.apache.cocoon.environment.SourceResolver; +import org.apache.cocoon.reading.AbstractReader; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.log4j.Logger; +import org.xml.sax.SAXException; +import org.dspace.app.xmlui.utils.ContextUtil; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; +import org.dspace.handle.HandleManager; + + +/** + * + * @author Pascal-Nicolas Becker (p dot becker at tu hyphen berlin dot de) + */ +public class HandleResolverReader extends AbstractReader implements Recyclable { + + private static final Logger log = Logger.getLogger(HandleResolverReader.class); + + public static final String CONTENTTYPE = "application/json; charset=utf-8"; + + private Request req; + private Response resp; + private String action; + private String handle; + private String prefix; + + + public void setup(SourceResolver resolver, Map objectModel, String src, + Parameters par) throws ProcessingException, SAXException, + IOException + { + this.req = ObjectModelHelper.getRequest(objectModel); + this.resp = ObjectModelHelper.getResponse(objectModel); + this.action = par.getParameter("action", "listprefixes"); + this.handle = par.getParameter("handle", null); + this.prefix = par.getParameter("prefix", null); + + super.setup(resolver, objectModel, src, par); + } + + @Override + public void generate() throws IOException, SAXException, ProcessingException { + Context context = null; + try { + context = ContextUtil.obtainContext(objectModel); + } catch (SQLException ex) { + log.error(ex); + throw new ProcessingException("Error in database conncetion.", ex); + } + + Gson gson = new Gson(); + String jsonString = null; + + try { + if (action.equals("resolve")) + { + if (StringUtils.isBlank(handle)) + { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + String url = HandleManager.resolveToURL(context, handle); + // Only an array or an abject is valid JSON. A simple string + // isn't. An object always uses key value pairs, so we use an + // array. + if (url != null) + { + jsonString = gson.toJson(new String[] {url}); + } + else + { + jsonString = gson.toJson(null); + } + } + else if (action.equals("listprefixes")) + { + List<String> prefixes = new ArrayList<String>(); + prefixes.add(HandleManager.getPrefix()); + String additionalPrefixes = ConfigurationManager + .getProperty("handle.additional.prefixes"); + if (StringUtils.isNotBlank(additionalPrefixes)) + { + for (String apref : additionalPrefixes.split(",")) + { + prefixes.add(apref.trim()); + } + } + jsonString = gson.toJson(prefixes); + } + else if (action.equals("listhandles")) + { + if (ConfigurationManager.getBooleanProperty( + "handle.hide.listhandles", true)) + { + resp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + if (StringUtils.isBlank(prefix)) + { + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + List<String> handlelist = HandleManager.getHandlesForPrefix( + context, prefix); + String[] handles = handlelist.toArray(new String[handlelist.size()]); + jsonString = gson.toJson(handles); + } + } catch (SQLException e) { + log.error("SQLException: ", e); + return; + } + + try { + ObjectModelHelper.getResponse(objectModel).setHeader("Content-Type", CONTENTTYPE); + ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonString.getBytes("UTF-8")); + IOUtils.copy(inputStream, out); + out.flush(); + } catch (Exception e) { + log.error("Error: ", e); + } + } + + public void recycle() { + this.req = null; + this.resp = null; + this.action = null; + this.handle = null; + this.prefix = null; + super.recycle(); + } +} \ No newline at end of file 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/ContainerHomePageMatcher.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/ContainerHomePageMatcher.java new file mode 100644 index 0000000000000000000000000000000000000000..b03b06f8c94541a15c052d6b186807d8a35f6c2b --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/ContainerHomePageMatcher.java @@ -0,0 +1,66 @@ +/** + * 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.avalon.framework.parameters.Parameters; +import org.apache.cocoon.matching.Matcher; +import org.apache.cocoon.sitemap.PatternException; +import org.apache.log4j.Logger; +import org.dspace.app.xmlui.utils.HandleUtil; +import org.dspace.discovery.SearchUtils; +import org.dspace.discovery.configuration.DiscoveryConfiguration; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; + +/** + * Matcher used to determine which transformers are used to render the home page for a community/collection + * + * @author Kevin Van de Velde (kevin at atmire dot com) + */ +public class ContainerHomePageMatcher implements Matcher { + + private static final Logger log = Logger.getLogger(ContainerHomePageMatcher.class); + + @Override + public Map match(String pattern, Map objectModel, Parameters parameters) throws PatternException { + boolean not = false; + int action = -1; // the action to check + + if (pattern.startsWith("!")) + { + not = true; + pattern = pattern.substring(1); + } + + if(pattern.equals("discoveryRecentSubmissions") || pattern.equals("metadata")) + { + try { + boolean isHomePageActive; + DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(HandleUtil.obtainHandle(objectModel)); + if(discoveryConfiguration.getRecentSubmissionConfiguration() != null && discoveryConfiguration.getRecentSubmissionConfiguration().getUseAsHomePage()) + { + isHomePageActive = !pattern.equals("metadata"); + } else{ + isHomePageActive = pattern.equals("metadata"); + } + if(isHomePageActive ^ not) + { + return new HashMap(); + }else{ + return null; + } + } catch (SQLException e) { + log.error("SQL exception while determining home page", e); + + } + } + throw new IllegalArgumentException(); + } +} 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/java/org/dspace/utils/DSpaceWebapp.java b/dspace-xmlui/src/main/java/org/dspace/utils/DSpaceWebapp.java new file mode 100644 index 0000000000000000000000000000000000000000..25a1df760c77ef13271a139aa7dce2454f1a0d2f --- /dev/null +++ b/dspace-xmlui/src/main/java/org/dspace/utils/DSpaceWebapp.java @@ -0,0 +1,31 @@ +/** + * 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.utils; + +import org.dspace.app.util.AbstractDSpaceWebapp; + +/** + * An MBean to identify this web application. + * + * @author mwood + */ +public class DSpaceWebapp + extends AbstractDSpaceWebapp +{ + public DSpaceWebapp() + { + super("XMLUI"); + } + + @Override + public boolean isUI() + { + return true; + } +} 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/icons/lock.gif b/dspace-xmlui/src/main/webapp/static/icons/lock.gif new file mode 100644 index 0000000000000000000000000000000000000000..3bfcaca23c4073db4c292e3fab4df5adacffc7da Binary files /dev/null and b/dspace-xmlui/src/main/webapp/static/icons/lock.gif differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/lock24.png b/dspace-xmlui/src/main/webapp/static/icons/lock24.png similarity index 100% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/lock24.png rename to dspace-xmlui/src/main/webapp/static/icons/lock24.png 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/images/creativecommons/cc-by-nc-nd.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc-nd.png new file mode 100644 index 0000000000000000000000000000000000000000..49f272f828c17c9f52b64c27fa6a3c399bee9344 Binary files /dev/null and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc-nd.png differ diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc-sa.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc-sa.png new file mode 100644 index 0000000000000000000000000000000000000000..0f2a0f10722d3fabffe8af5d5eed09866e25909a Binary files /dev/null and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc-sa.png differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_minus.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc.png similarity index 50% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_minus.png rename to dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc.png index 45ad7c36d863dd1dfea17841d594d44d8a8db649..5f982147075ad08691e3b3c53e92633ca0ddcb2f 100644 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_minus.png and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nc.png differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/check_606060_15x15.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nd.png similarity index 53% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/check_606060_15x15.png rename to dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nd.png index 8648de74b2edf7f76b2025ccec11d7d33f36fce5..8f317035e677affa946516c82baa17f896e8a866 100644 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/check_606060_15x15.png and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-nd.png differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_plus.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-sa.png similarity index 51% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_plus.png rename to dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-sa.png index 2da6ee744a8df82ed7a7ce5c4f2831874963c14f..f0a944e0b89642ae282047846e55393007b04686 100644 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/button_plus.png and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by-sa.png differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_6D859C_25x25.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by.png similarity index 55% rename from dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_6D859C_25x25.png rename to dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by.png index 089d864b45f346dbd5720cfba32a1d5abcf06773..822491edb993b072fc183a2ce23adfa8c94cee7c 100644 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_6D859C_25x25.png and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-by.png differ diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-generic.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-generic.png new file mode 100644 index 0000000000000000000000000000000000000000..4590b0a7a047efa3c7ec5d724c79434390444bf4 Binary files /dev/null and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-generic.png differ diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-mark.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-mark.png new file mode 100644 index 0000000000000000000000000000000000000000..f1eafe1d83d45cda9b5cf69c7fc680156fc8422f Binary files /dev/null and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-mark.png differ diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-zero.png b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-zero.png new file mode 100644 index 0000000000000000000000000000000000000000..59f27f3000045e384fbf45b8b436c5b9935f683b Binary files /dev/null and b/dspace-xmlui/src/main/webapp/themes/Mirage/images/creativecommons/cc-zero.png differ 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.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/DIM2DataCite.xsl b/dspace/config/crosswalks/DIM2DataCite.xsl new file mode 100644 index 0000000000000000000000000000000000000000..0c25adfb4c75a5fd83b42c9ed7da160e68769032 --- /dev/null +++ b/dspace/config/crosswalks/DIM2DataCite.xsl @@ -0,0 +1,439 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Document : DIM2DataCite.xsl + Created on : January 23, 2013, 1:26 PM + Author : pbecker, ffuerste + Description: Converts metadata from DSpace Intermediat Format (DIM) into + metadata following the DataCite Schema for the Publication and + Citation of Research Data, Version 2.2 +--> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:dspace="http://www.dspace.org/xmlns/dspace/dim" + xmlns="http://datacite.org/schema/kernel-2.2" + version="1.0"> + + <!-- CONFIGURATION --> + <!-- The content of the following variable will be used as element publisher. --> + <xsl:variable name="publisher">My University</xsl:variable> + <!-- The content of the following variable will be used as element contributor with contributorType datamanager. --> + <xsl:variable name="datamanager"><xsl:value-of select="$publisher" /></xsl:variable> + <!-- The content of the following variable will be used as element contributor with contributorType hostingInstitution. --> + <xsl:variable name="hostinginstitution"><xsl:value-of select="$publisher" /></xsl:variable> + <!-- Please take a look into the DataCite schema documentation if you want to know how to use these elements. + http://schema.datacite.org --> + + + <!-- DO NOT CHANGE ANYTHING BELOW THIS LINE EXCEPT YOU REALLY KNOW WHAT YOU ARE DOING! --> + + <xsl:output method="xml" indent="yes" encoding="utf-8" /> + + <!-- Don't copy everything by default! --> + <xsl:template match="@* | text()" /> + + <xsl:template match="/dspace:dim[@dspaceType='ITEM']"> + <!-- + org.dspace.identifier.doi.DataCiteConnector uses this XSLT to + transform metadata for the DataCite metadata store. This crosswalk + should only be used, when it is ensured that all mandatory + properties are in the metadata of the item to export. + The classe named above respects this. + --> + <resource xmlns="http://datacite.org/schema/kernel-2.2" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://datacite.org/schema/kernel-2.2 http://schema.datacite.org/meta/kernel-2.2/metadata.xsd"> + + <!-- + MANDATORY PROPERTIES + --> + + <!-- + DataCite (1) + Template Call for DOI identifier. + --> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='identifier' and starts-with(., 'http://dx.doi.org/')]" /> + + <!-- + DataCite (2) + Add creator information. + --> + <creators> + <xsl:choose> + <xsl:when test="//dspace:field[@mdschema='dc' and @element='contributor' and @qualifier='author']"> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='contributor' and @qualifier='author']" /> + </xsl:when> + <xsl:otherwise> + <creator> + <creatorName>(:unkn) unknown</creatorName> + </creator> + </xsl:otherwise> + </xsl:choose> + </creators> + + <!-- + DataCite (3) + Add Title information. + --> + <titles> + <xsl:choose> + <xsl:when test="//dspace:field[@mdschema='dc' and @element='title']"> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='title']" /> + </xsl:when> + <xsl:otherwise> + <title>(:unas) unassigned</title> + </xsl:otherwise> + </xsl:choose> + </titles> + + <!-- + DataCite (4) + Add Publisher information from configuration above + --> + <publisher> + <xsl:value-of select="$publisher" /> + </publisher> + + <!-- + DataCite (5) + Add PublicationYear information + --> + <publicationYear> + <xsl:choose> + <xsl:when test="//dspace:field[@mdschema='dc' and @element='date' and @qualifier='issued']"> + <xsl:value-of select="substring(//dspace:field[@mdschema='dc' and @element='date' and @qualifier='issued'], 1, 4)" /> + </xsl:when> + <xsl:when test="//dspace:field[@mdschema='dc' and @element='date' and @qualifier='available']"> + <xsl:value-of select="substring(//dspace:field[@mdschema='dc' and @element='date' and @qualifier='issued'], 1, 4)" /> + </xsl:when> + <xsl:when test="//dspace:field[@mdschema='dc' and @element='date']"> + <xsl:value-of select="substring(//dspace:field[@mdschema='dc' and @element='date'], 1, 4)" /> + </xsl:when> + <xsl:otherwise>0000</xsl:otherwise> + </xsl:choose> + </publicationYear> + + <!-- + OPTIONAL PROPERTIES + --> + + <!-- + DataCite (6) + Template Call for subjects. + --> + <xsl:if test="//dspace:field[@mdschema='dc' and @element='subject']"> + <subjects> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='subject']" /> + </subjects> + </xsl:if> + + <!-- + DataCite (7) + Add contributorType from configuration above. + Template Call for Contributors + --> + <contributors> + <xsl:element name="contributor"> + <xsl:attribute name="contributorType">DataManager</xsl:attribute> + <xsl:element name="contributorName"> + <xsl:value-of select="$datamanager"/> + </xsl:element> + </xsl:element> + <xsl:element name="contributor"> + <xsl:attribute name="contributorType">HostingInstitution</xsl:attribute> + <contributorName> + <xsl:value-of select="$hostinginstitution" /> + </contributorName> + </xsl:element> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='contributor'][not(@qualifier='author')]" /> + </contributors> + + <!-- + DataCite (8) + Template Call for Dates + --> + <xsl:if test="//dspace:field[@mdschema='dc' and @element='date']" > + <dates> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='date']" /> + </dates> + </xsl:if> + + <!-- Add language(s). --> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='language' and (@qualifier='iso' or @qualifier='rfc3066')]" /> + + <!-- Add resource type. --> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='type']" /> + + <!-- + Add alternativeIdentifiers. + This element is important as it is used to recognize for which + DSpace object a DOI is reserved for. See below for further + information. + --> + <xsl:if test="//dspace:field[@mdschema='dc' and @element='identifier' and not(starts-with(., 'http://dx.doi.org/'))]"> + <xsl:element name="alternateIdentifiers"> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='identifier' and not(starts-with(., 'http://dx.doi.org/'))]" /> + </xsl:element> + </xsl:if> + + <!-- Add sizes. --> + <!-- + <xsl:if test="//dspace:field[@mdschema='dc' and @element='format' and @qualifier='extent']"> + <sizes> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='format' and @qualifier='extent']" /> + </sizes> + </xsl:if> + --> + + <!-- Add formats. --> + <!-- + <xsl:if test="//dspace:field[@mdschema='dc' and @element='format']"> + <formats> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='format']" /> + </formats> + </xsl:if> + --> + + <!-- Add rights. --> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='rights']" /> + + <!-- Add descriptions. --> + <xsl:if test="//dspace:field[@mdschema='dc' and @element='description'][not(@qualifier='provenance')]"> + <xsl:element name="descriptions"> + <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='description'][not(@qualifier='provenance')]" /> + </xsl:element> + </xsl:if> + + </resource> + </xsl:template> + + + <!-- Add doi identifier information. --> + <xsl:template match="dspace:field[@mdschema='dc' and @element='identifier' and starts-with(., 'http://dx.doi.org/')]"> + <identifier identifierType="DOI"> + <xsl:value-of select="substring(., 19)"/> + </identifier> + </xsl:template> + + <!-- DataCite (2) :: Creator --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='contributor' and @qualifier='author']"> + <creator> + <creatorName> + <xsl:value-of select="." /> + </creatorName> + </creator> + </xsl:template> + + <!-- DataCite (3) :: Title --> + <xsl:template match="dspace:field[@mdschema='dc' and @element='title']"> + <xsl:element name="title"> + <xsl:if test="@qualifier='alternative'"> + <xsl:attribute name="titleType">AlternativeTitle</xsl:attribute> + </xsl:if> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (6), DataCite (6.1) + Adds subject and subjectScheme information + + "This term is intended to be used with non-literal values as defined in the + DCMI Abstract Model (http://dublincore.org/documents/abstract-model/). + As of December 2007, the DCMI Usage Board is seeking a way to express + this intention with a formal range declaration." + (http://dublincore.org/documents/dcmi-terms/#terms-subject) + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='subject']"> + <xsl:element name="subject"> + <xsl:if test="@qualifier"> + <xsl:attribute name="subjectScheme"><xsl:value-of select="@qualifier" /></xsl:attribute> + </xsl:if> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (7), DataCite (7.1) + Adds contributor and contributorType information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='contributor'][not(@qualifier='author')]"> + <xsl:if test="@qualifier='editor'"> + <xsl:element name="contributor"> + <xsl:attribute name="contributorType">Editor</xsl:attribute> + <contributorName> + <xsl:value-of select="." /> + </contributorName> + </xsl:element> + </xsl:if> + </xsl:template> + + <!-- + DataCite (8), DataCite (8.1) + Adds Date and dateType information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='date']"> + <xsl:element name="date"> + <xsl:if test="@qualifier='accessioned'"> + <xsl:attribute name="dateType">Issued</xsl:attribute> + </xsl:if> + <xsl:if test="@qualifier='submitted'"> + <xsl:attribute name="dateType">Issued</xsl:attribute> + </xsl:if> + <!-- part of DublinCore DSpace to mapping but not part of DSpace default fields + <xsl:if test="@qualifier='dateAccepted'"> + <xsl:attribute name="dateType">Issued</xsl:attribute> + </xsl:if> + --> + <xsl:if test="@qualifier='issued'"> + <xsl:attribute name="dateType">Issued</xsl:attribute> + </xsl:if> + <xsl:if test="@qualifier='available'"> + <xsl:attribute name="dateType">Available</xsl:attribute> + </xsl:if> + <xsl:if test="@qualifier='copyright'"> + <xsl:attribute name="dateType">Copyrighted</xsl:attribute> + </xsl:if> + <xsl:if test="@qualifier='created'"> + <xsl:attribute name="dateType">Created</xsl:attribute> + </xsl:if> + <xsl:if test="@qualifier='updated'"> + <xsl:attribute name="dateType">Updated</xsl:attribute> + </xsl:if> + <xsl:value-of select="substring(., 1, 10)" /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (9) + Adds Language information + Transforming the language flags according to ISO 639-2/B & ISO 639-3 + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='language' and (@qualifier='iso' or @qualifier='rfc3066')]"> + <xsl:for-each select="."> + <xsl:element name="language"> + <xsl:choose> + <xsl:when test="contains(string(text()), '_')"> + <xsl:value-of select="translate(string(text()), '_', '-')"/> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="string(text())"/> + </xsl:otherwise> + </xsl:choose> + </xsl:element> + </xsl:for-each> + </xsl:template> + + <!-- + DataCite (10), DataCite (10.1) + Adds resourceType and resourceTypeGeneral information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='type']"> + <xsl:for-each select="."> + <!-- Transforming the language flags according to ISO 639-2/B & ISO 639-3 --> + <xsl:element name="resourceType"> + <xsl:attribute name="resourceTypeGeneral"> + <xsl:choose> + <xsl:when test="string(text())='Animation'">Image</xsl:when> + <xsl:when test="string(text())='Article'">Text</xsl:when> + <xsl:when test="string(text())='Book'">Text</xsl:when> + <xsl:when test="string(text())='Book chapter'">Text</xsl:when> + <xsl:when test="string(text())='Dataset'">Dataset</xsl:when> + <xsl:when test="string(text())='Learning Object'">InteractiveResource</xsl:when> + <xsl:when test="string(text())='Image'">Image</xsl:when> + <xsl:when test="string(text())='Image, 3-D'">Image</xsl:when> + <xsl:when test="string(text())='Map'">Image</xsl:when> + <xsl:when test="string(text())='Musical Score'">Sound</xsl:when> + <xsl:when test="string(text())='Plan or blueprint'">Image</xsl:when> + <xsl:when test="string(text())='Preprint'">Text</xsl:when> + <xsl:when test="string(text())='Presentation'">Image</xsl:when> + <xsl:when test="string(text())='Recording, acoustical'">Sound</xsl:when> + <xsl:when test="string(text())='Recording, musical'">Sound</xsl:when> + <xsl:when test="string(text())='Recording, oral'">Sound</xsl:when> + <xsl:when test="string(text())='Software'">Software</xsl:when> + <xsl:when test="string(text())='Technical Report'">Text</xsl:when> + <xsl:when test="string(text())='Thesis'">Text</xsl:when> + <xsl:when test="string(text())='Video'">Film</xsl:when> + <xsl:when test="string(text())='Working Paper'">Text</xsl:when> + <!-- FIXME --> + <xsl:when test="string(text())='Other'">Collection</xsl:when> + <!-- FIXME --> + <xsl:otherwise>Collection</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:value-of select="." /> + </xsl:element> + </xsl:for-each> + </xsl:template> + + <!-- + DataCite (11), DataCite (11.1) + Adds AlternativeIdentifier and alternativeIdentifierType information + Adds all identifiers except the doi. + + This element is important as it is used to recognize for which DSpace + objet a DOI is reserved for. The DataCiteConnector will test all + AlternativeIdentifiers by using HandleManager. + resolveUrlToHandle(context, altId) until one is recognized or all have + been tested. + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='identifier' and not(starts-with(., 'http://dx.doi.org/'))]"> + <xsl:element name="alternateIdentifier"> + <xsl:if test="@qualifier"> + <xsl:attribute name="alternateIdentifierType"><xsl:value-of select="@qualifier" /></xsl:attribute> + </xsl:if> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (12), DataCite (12.1) + Adds RelatedIdentifier and relatedIdentifierType information + --> + + <!-- + DataCite (13) + Adds Size information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='format' and @qualifier='extent']"> + <xsl:element name="format"> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (14) + Adds Format information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='format']"> + <xsl:element name="format"> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (16) + Adds Rights information + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='rights']"> + <xsl:element name="rights"> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + + <!-- + DataCite (17) + Description + --> + <xsl:template match="//dspace:field[@mdschema='dc' and @element='description'][not(@qualifier='provenance')]"> + <xsl:element name="description"> + <xsl:attribute name="descriptionType"> + <xsl:choose> + <xsl:when test="@qualifier='abstract'">Abstract</xsl:when> + <xsl:otherwise>Other</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <xsl:value-of select="." /> + </xsl:element> + </xsl:template> + +</xsl:stylesheet> 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/mapConverter-arxivSubject.properties b/dspace/config/crosswalks/mapConverter-arxivSubject.properties new file mode 100644 index 0000000000000000000000000000000000000000..d6b8a257b55514afc2bf254a250fc921f71a4afe --- /dev/null +++ b/dspace/config/crosswalks/mapConverter-arxivSubject.properties @@ -0,0 +1,127 @@ +stat.AP = Statistics - Applications +stat.CO = Statistics - Computation +stat.ML = Statistics - Machine Learning +stat.ME = Statistics - Methodology +stat.TH = Statistics - Theory +q-bio.BM = Quantitative Biology - Biomolecules +q-bio.CB = Quantitative Biology - Cell Behavior +q-bio.GN = Quantitative Biology - Genomics +q-bio.MN = Quantitative Biology - Molecular Networks +q-bio.NC = Quantitative Biology - Neurons and Cognition +q-bio.OT = Quantitative Biology - Other +q-bio.PE = Quantitative Biology - Populations and Evolution +q-bio.QM = Quantitative Biology - Quantitative Methods +q-bio.SC = Quantitative Biology - Subcellular Processes +q-bio.TO = Quantitative Biology - Tissues and Organs +cs.AR = Computer Science - Architecture +cs.AI = Computer Science - Artificial Intelligence +cs.CL = Computer Science - Computation and Language +cs.CC = Computer Science - Computational Complexity +cs.CE = Computer Science - Computational Engineering; Finance; and Science +cs.CG = Computer Science - Computational Geometry +cs.GT = Computer Science - Computer Science and Game Theory +cs.CV = Computer Science - Computer Vision and Pattern Recognition +cs.CY = Computer Science - Computers and Society +cs.CR = Computer Science - Cryptography and Security +cs.DS = Computer Science - Data Structures and Algorithms +cs.DB = Computer Science - Databases +cs.DL = Computer Science - Digital Libraries +cs.DM = Computer Science - Discrete Mathematics +cs.DC = Computer Science - Distributed; Parallel; and Cluster Computing +cs.GL = Computer Science - General Literature +cs.GR = Computer Science - Graphics +cs.HC = Computer Science - Human-Computer Interaction +cs.IR = Computer Science - Information Retrieval +cs.IT = Computer Science - Information Theory +cs.LG = Computer Science - Learning +cs.LO = Computer Science - Logic in Computer Science +cs.MS = Computer Science - Mathematical Software +cs.MA = Computer Science - Multiagent Systems +cs.MM = Computer Science - Multimedia +cs.NI = Computer Science - Networking and Internet Architecture +cs.NE = Computer Science - Neural and Evolutionary Computing +cs.NA = Computer Science - Numerical Analysis +cs.OS = Computer Science - Operating Systems +cs.OH = Computer Science - Other +cs.PF = Computer Science - Performance +cs.PL = Computer Science - Programming Languages +cs.RO = Computer Science - Robotics +cs.SE = Computer Science - Software Engineering +cs.SD = Computer Science - Sound +cs.SC = Computer Science - Symbolic Computation +nlin.AO = Nonlinear Sciences - Adaptation and Self-Organizing Systems +nlin.CG = Nonlinear Sciences - Cellular Automata and Lattice Gases +nlin.CD = Nonlinear Sciences - Chaotic Dynamics +nlin.SI = Nonlinear Sciences - Exactly Solvable and Integrable Systems +nlin.PS = Nonlinear Sciences - Pattern Formation and Solitons +math.AG = Mathematics - Algebraic Geometry +math.AT = Mathematics - Algebraic Topology +math.AP = Mathematics - Analysis of PDEs +math.CT = Mathematics - Category Theory +math.CA = Mathematics - Classical Analysis and ODEs +math.CO = Mathematics - Combinatorics +math.AC = Mathematics - Commutative Algebra +math.CV = Mathematics - Complex Variables +math.DG = Mathematics - Differential Geometry +math.DS = Mathematics - Dynamical Systems +math.FA = Mathematics - Functional Analysis +math.GM = Mathematics - General Mathematics +math.GN = Mathematics - General Topology +math.GT = Mathematics - Geometric Topology +math.GR = Mathematics - Group Theory +math.HO = Mathematics - History and Overview +math.IT = Mathematics - Information Theory +math.KT = Mathematics - K-Theory and Homology +math.LO = Mathematics - Logic +math.MP = Mathematics - Mathematical Physics +math.MG = Mathematics - Metric Geometry +math.NT = Mathematics - Number Theory +math.NA = Mathematics - Numerical Analysis +math.OA = Mathematics - Operator Algebras +math.OC = Mathematics - Optimization and Control +math.PR = Mathematics - Probability +math.QA = Mathematics - Quantum Algebra +math.RT = Mathematics - Representation Theory +math.RA = Mathematics - Rings and Algebras +math.SP = Mathematics - Spectral Theory +math.ST = Mathematics - Statistics +math.SG = Mathematics - Symplectic Geometry +astro-ph = Astrophysics +cond-mat.dis-nn = Physics - Disordered Systems and Neural Networks +cond-mat.mes-hall = Physics - Mesoscopic Systems and Quantum Hall Effect +cond-mat.mtrl-sci = Physics - Materials Science +cond-mat.other = Physics - Other +cond-mat.soft = Physics - Soft Condensed Matter +cond-mat.stat-mech = Physics - Statistical Mechanics +cond-mat.str-el = Physics - Strongly Correlated Electrons +cond-mat.supr-con = Physics - Superconductivity +gr-qc = General Relativity and Quantum Cosmology +hep-ex = High Energy Physics - Experiment +hep-lat = High Energy Physics - Lattice +hep-ph = High Energy Physics - Phenomenology +hep-th = High Energy Physics - Theory +math-ph = Mathematical Physics +nucl-ex = Nuclear Experiment +nucl-th = Nuclear Theory +physics.acc-ph = Physics - Accelerator Physics +physics.ao-ph = Physics - Atmospheric and Oceanic Physics +physics.atom-ph = Physics - Atomic Physics +physics.atm-clus = Physics - Atomic and Molecular Clusters +physics.bio-ph = Physics - Biological Physics +physics.chem-ph = Physics - Chemical Physics +physics.class-ph = Physics - Classical Physics +physics.comp-ph = Physics - Computational Physics +physics.data-an = Physics - Data Analysis; Statistics and Probability +physics.flu-dyn = Physics - Fluid Dynamics +physics.gen-ph = Physics - General Physics +physics.geo-ph = Physics - Geophysics +physics.hist-ph = Physics - History of Physics +physics.ins-det = Physics - Instrumentation and Detectors +physics.med-ph = Physics - Medical Physics +physics.optics = Physics - Optics +physics.ed-ph = Physics - Physics Education +physics.soc-ph = Physics - Physics and Society +physics.plasm-ph = Physics - Plasma Physics +physics.pop-ph = Physics - Popular Physics +physics.space-ph = Physics - Space Physics +quant-ph = Quantum Physics \ No newline at end of file diff --git a/dspace/config/crosswalks/mapConverter-pubstatusPubmed.properties b/dspace/config/crosswalks/mapConverter-pubstatusPubmed.properties new file mode 100644 index 0000000000000000000000000000000000000000..43d4d65027c62f636ceac07817ec427c5db9a1e0 --- /dev/null +++ b/dspace/config/crosswalks/mapConverter-pubstatusPubmed.properties @@ -0,0 +1,2 @@ +ppublish = Published +epublish = Published \ No newline at end of file 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..f7e50d451e69f5a9db62ad24b2e34c758b8a5663 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -36,7 +36,7 @@ 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 @@ -107,6 +107,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 +233,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 +341,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 @@ -472,6 +505,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 +678,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 +714,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 +770,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 +797,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 +812,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 +830,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 +876,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 +910,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 +925,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 +1008,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 +1221,95 @@ 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 #### Submission License substitution variables #### # it is possible include contextual information in the submission license using substitution variables @@ -1308,6 +1480,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 +1522,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 +1592,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 +1769,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 +1843,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 +1850,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 +1862,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 +1885,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 +1957,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_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/emails/bkp.export_error b/dspace/config/emails/bte_batch_import_error similarity index 54% rename from dspace/config/emails/bkp.export_error rename to dspace/config/emails/bte_batch_import_error index 571df69553bde9b50bb325353acce26b0615cf47..11657f29df914c752364a9e9812cdfadd26dc375 100644 --- a/dspace/config/emails/bkp.export_error +++ b/dspace/config/emails/bte_batch_import_error @@ -1,4 +1,4 @@ -# Email sent to DSpace users when they successfully export an item or collection. +# Email sent to DSpace users when they BTE batch import fails. # # Parameters: {0} the export error # {1} the URL to the feedback page @@ -6,8 +6,8 @@ # # 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: +Subject: DSpace - The batch import was not completed. +The batch import you initiated from the DSpace UI was not completed, due to the following reason: {0} For more information you may contact your system administrator: diff --git a/dspace/config/emails/bte_batch_import_success b/dspace/config/emails/bte_batch_import_success new file mode 100644 index 0000000000000000000000000000000000000000..930ccd82aed61c7b20cc6712549ff8d06bbc1082 --- /dev/null +++ b/dspace/config/emails/bte_batch_import_success @@ -0,0 +1,15 @@ +# Email sent to DSpace users when they successfully batch import items via BTE. +# +# Parameters: {0} the filepath to the mapfile created by the batch import +# +# +# See org.dspace.core.Email for information on the format of this file. +# +Subject: DSpace - Batch import successfully completed +The batch item import you initiated from the DSpace UI has completed successfully. + +You may find the mapfile for the import in the following path: {0} + + +The DSpace Team + diff --git a/dspace/config/emails/change_password b/dspace/config/emails/change_password index 4e1dcf2b2a378a118868747c6edb1f802d29e8be..9fca59f3401108ebda756095e3b7d3323b3564dc 100644 --- a/dspace/config/emails/change_password +++ b/dspace/config/emails/change_password @@ -4,17 +4,13 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: Alteração de senha +Subject: Change Password Request +To change the password for your DSpace account, please click the link +below: -Recebemos sua solicitação de recuperação de senha. -Para alterá-la, clique em: + {0} - {0} - -Se você não solicitou a recuperação da senha, ignore esta mensagem. - - - -Atenciosamente, -Equipe Participatório +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/doi_maintenance_error b/dspace/config/emails/doi_maintenance_error new file mode 100644 index 0000000000000000000000000000000000000000..be60904e7cd3c3e2b0f96eed79f1225eabf0bbee --- /dev/null +++ b/dspace/config/emails/doi_maintenance_error @@ -0,0 +1,18 @@ +# E-mail sent to designated address when a metadata update, registration +# or reserveration of a doi fails +# +# Parameters: {0} action (updating metadata of, registering or reserving) +# {1} Date & Time +# {2} resource type text +# {3} resource id +# {4} doi +# {5} reason +# +# See org.dspace.core.Email for information on the format of this file. +# +Subject: DSpace: Error {0} DOI {3} + +Date: {1} + +{0} DOI {4} for {2} with ID {3} failed: +{5} diff --git a/dspace/config/emails/export_error b/dspace/config/emails/export_error index 49b99b63457c74fc275a75e7914c61938cfb5d05..571df69553bde9b50bb325353acce26b0615cf47 100644 --- a/dspace/config/emails/export_error +++ b/dspace/config/emails/export_error @@ -6,14 +6,14 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: Dspace - Sua solicitação de exportação de item não foi concluÃda -Sua solicitação de exportação de item não foi concluÃda, devido a: +Subject: DSpace - The item export you requested was not completed. +The item export you requested was not completed, due to the following reason: {0} -Para maiores informações você deve contatar o Administrador do sistema: +For more information you may contact your system administrator: {1} -Atenciosamente, -Equipe Participatório +The DSpace Team + diff --git a/dspace/config/emails/export_success b/dspace/config/emails/export_success index eda95606e5197a0624f47ba078e3774c8478a4dd..2396e5ce5e14f4374222000a037014872175baa3 100644 --- a/dspace/config/emails/export_success +++ b/dspace/config/emails/export_success @@ -5,15 +5,14 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: DSpace - O item que você exportou está pronto para download -Sua solicitação de exportação de item foi concluÃda e está pronta para download. +Subject: DSpace - Item export requested is ready for download +The item export you requested from the repository is now ready for download. -Você pode baixar o arquivo através do seguinte link: +You may download the compressed file using the following link: {0} -Este arquivo ficará disponÃvel por pelo menos {1} horas. +This file will remain available for at least {1} hours. +The DSpace Team -Atenciosamente, -Equipe Participatório diff --git a/dspace/config/emails/feedback b/dspace/config/emails/feedback index 5a28d928383f3066c58392c61699417edc7c63b7..e7f972e4b5b12a35b3930a038901f34cd5c868d6 100644 --- a/dspace/config/emails/feedback +++ b/dspace/config/emails/feedback @@ -10,17 +10,17 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: Formulario de Feedback +Subject: Feedback Form Information -Comentários: +Comments: {6} -Data: {0} +Date: {0} Email: {1} -Loggado como: {2} -Página em que estava: {3} +Logged In As: {2} +Referring Page: {3} User Agent: {4} -Sessão: {5} +Session: {5} diff --git a/dspace/config/emails/flowtask_notify b/dspace/config/emails/flowtask_notify index 046557c5118b152e62f2676a714d74da8def5ee2..4b494180e77c8474ad944f4ab8a41e7a9008a21a 100644 --- a/dspace/config/emails/flowtask_notify +++ b/dspace/config/emails/flowtask_notify @@ -7,19 +7,17 @@ # {4} Task result # {5} Workflow action taken # -Subject: DSpace: Relatório de curadoria +Subject: DSpace: Curation Task Report -TÃtulo: {0} -Coleção: {1} -Submetido por: {2} +Title: {0} +Collection: {1} +Submitted by: {2} -Tarefa de Curadoria "{3}" realizada com o seguinte resultado: +Curation task {3} has been performed +with the following result: {4} -Ação tomada na submissão: {5} +Action taken on the submission: {5} - - -Atenciosamente, -Equipe Participatório +DSpace diff --git a/dspace/config/emails/register b/dspace/config/emails/register index d28e96a8a78e8bedfaa05ccde584816f852564ce..7439da86dd4dccce4ace9588a6d8d3f5a4df77e4 100644 --- a/dspace/config/emails/register +++ b/dspace/config/emails/register @@ -4,16 +4,13 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: Dspace - Cadastro de conta -Para confirmar seu email e completar seu cadastro clique no link abaixo: +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. -Se você não tentou se cadastrar no Dspace do projeto Participatório, -ignore esta mensagem. - - - -Atenciosamente, -Equipe Participatório +The DSpace Team diff --git a/dspace/config/emails/registration_notify b/dspace/config/emails/registration_notify index 655d005b14ead6558e78805a0520485a1e784e92..9802ae887d48a3cdd2b4a26bc187f78c789c37cf 100644 --- a/dspace/config/emails/registration_notify +++ b/dspace/config/emails/registration_notify @@ -8,11 +8,10 @@ # # See org.dspace.core.Email for information on the format of this file. # -Subject: DSpace: Notificação de cadastro de usuario +Subject: DSpace: Registration Notification -Um novo usuário se cadastrou no {0} em {1}: +A new user has registered on {0} at {1}: -Nome: {2} +Name: {2} Email: {3} -Data: {4} - +Date: {4} diff --git a/dspace/config/emails/request_item.admin b/dspace/config/emails/request_item.admin new file mode 100644 index 0000000000000000000000000000000000000000..7611efb2048ce6b979d55d5d9d5712b4052e08a0 --- /dev/null +++ b/dspace/config/emails/request_item.admin @@ -0,0 +1,8 @@ +Subject: Request for Open Access + +{3}, with address {4}, +requested the following document/file to be in Open Access: + +Document Handle:{1} +File ID: {0} +Token:{2} \ No newline at end of file diff --git a/dspace/config/emails/request_item.author b/dspace/config/emails/request_item.author new file mode 100644 index 0000000000000000000000000000000000000000..3ea529f46dee39c721197db0a9ca78a255a9d0b9 --- /dev/null +++ b/dspace/config/emails/request_item.author @@ -0,0 +1,17 @@ +Subject: Request copy of document + +Dear {7}, + +A user of {9}, named {0} and using the email {1}, requested a copy of the file(s) associated with the document: "{4}" ({3}) submitted by you. + +This request came along with the following message: + +"{5}" + +To answer, click {6}. Whether you choose to grant or deny the request, we think that it''s in your best interest to respond. + +IF YOU ARE NOT AN AUTHOR OF THIS DOCUMENT, and only submitted the document on the author''s behalf, PLEASE REDIRECT THIS MESSAGE TO THE AUTHOR(S). Only the author(s) should answer the request to send a copy. + +IF YOU ARE AN AUTHOR OF THE REQUESTED DOCUMENT, thank you for your cooperation! + +If you have any questions concerning this request, please contact {10}. \ No newline at end of file diff --git a/dspace/config/emails/submit_archive b/dspace/config/emails/submit_archive index 6f71c704b60af4b242b423acc531d5c721978781..39e3c105a2d4fa3bc7a57d5c254bcca029aff2a0 100644 --- a/dspace/config/emails/submit_archive +++ b/dspace/config/emails/submit_archive @@ -4,19 +4,18 @@ # {1} Name of collection # {2} handle # -Subject: DSpace: Submissão aprovada e arquivada +Subject: DSpace: Submission Approved and Archived -Você submeteu: {0} +You submitted: {0} -Para a coleção: {1} +To collection: {1} -Sua submissão foi aceita e está agora qrquivada no Dspace, -e foi atribuÃda ao seguinte identificador: - {2} +Your submission has been accepted and archived in DSpace, +and it has been assigned the following identifier: +{2} -Por favor use este identificador quando citar sua submissão. +Please use this identifier when citing your submission. +Many thanks! - -Atenciosamente, -Equipe Participatório +DSpace diff --git a/dspace/config/emails/submit_reject b/dspace/config/emails/submit_reject index 14c7b1115153a7d40b0709ee24ec1e93ae629e7d..7408546462531c2e009a917fb8dfc45fa873eac8 100644 --- a/dspace/config/emails/submit_reject +++ b/dspace/config/emails/submit_reject @@ -6,21 +6,18 @@ # {3} Reason for the rejection # {4} Link to 'My DSpace' page # -Subject: DSpace: Submissão rejeitada +Subject: DSpace: Submission Rejected -Você submeteu: {0} +You submitted: {0} -Para a coleção: {1} +To collection: {1} -Sua submissão foi rejeitada por {2} -com a seguinte explicação: +Your submission has been rejected by {2} +with the following explanation: {3} -Sua submissão não foi deletada, Você pode acessála através -de sua página pessoal: {4} +Your submission has not been deleted. You can access it from your +"My DSpace" page: {4} - - -Atenciosamente, -Equipe Participatório +DSpace diff --git a/dspace/config/emails/submit_task b/dspace/config/emails/submit_task index 3915111c2d946ebe8040330a1c5bc553d160c796..b2354c8252321458e4298559d07ccbd2cc39066f 100644 --- a/dspace/config/emails/submit_task +++ b/dspace/config/emails/submit_task @@ -6,20 +6,19 @@ # {3} Description of task # {4} link to 'my DSpace' page # -Subject: DSpace: Novo item submetido +Subject: DSpace: You have a new task -Um novo Item foi submetido: +A new item has been submitted: -TÃtulo: {0} -Coleção: {1} -Submetido por: {2} +Title: {0} +Collection: {1} +Submitted by: {2} {3} -Para obter esta tarefa, visite sua página pessoal: - {4} +To claim this task, please visit your "My DSpace" +page: {4} +Many thanks! - -Atenciosamente, -Equipe Participatório +DSpace diff --git a/dspace/config/emails/subscription b/dspace/config/emails/subscription index 026480a7638e689842e3f3ffb7d51035caa357de..6310a36c3654bb95b8dd67d8d6f3314d87065c5e 100644 --- a/dspace/config/emails/subscription +++ b/dspace/config/emails/subscription @@ -4,12 +4,9 @@ # 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: Boletim DSpace -Novos itens foram adicionados a coleções que você assinou: +Subject: DSpace Subscription +New items are available in the collections you have subscribed to: {0} - - -Atenciosamente, -Equipe Participatório +DSpace diff --git a/dspace/config/emails/suggest b/dspace/config/emails/suggest index fbedc230576c697f703d2e08d4f349868af0ecad..4c4db3efac07b6b4089628b848e5e7f84b7ffa5a 100644 --- a/dspace/config/emails/suggest +++ b/dspace/config/emails/suggest @@ -10,17 +10,17 @@ # {7} sender message # See org.dspace.core.Email for information on the format of this file. # -Subject: Um item de interesse do Dspace +Subject: An item of interest from DSpace -Olá, {0}: +Hello {0}: -{1} requisitou que mandássemos este email sobre um item disponivel em {2}. +{1} requested we send you this email regarding an item available in {2}. -TÃtulo: {3} -Local: {5} -Na coleção: {6} -Mensagem pessoal: {7} +Title: {3} +Location: {5} +In Collection: {6} +Personal Message: {7} -O repositório digital Dspace captura, armazena, indexa, preserva e distribui material digital. -Para mais informações, visite www.dspace.org +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..8202d520a08d57ef764fd21fffd989f26718adf7 100644 --- a/dspace/config/input-forms.xml +++ b/dspace/config/input-forms.xml @@ -43,9 +43,9 @@ <dc-element>contributor</dc-element> <dc-qualifier>author</dc-qualifier> <repeatable>true</repeatable> - <label>Autor</label> + <label>Authors</label> <input-type>name</input-type> - <hint>insira abaixo o nome dos autores deste item.</hint> + <hint>Enter the names of the authors of this item below.</hint> <required></required> </field> @@ -54,10 +54,10 @@ <dc-element>title</dc-element> <dc-qualifier></dc-qualifier> <repeatable>false</repeatable> - <label>TÃtulo</label> + <label>Title</label> <input-type>onebox</input-type> - <hint>Insira o tÃtulo principal deste item.</hint> - <required>Você deve inserir um tÃtulo para este item.</required> + <hint>Enter the main title of the item.</hint> + <required>You must enter a main title for this item.</required> </field> <field> @@ -65,9 +65,9 @@ <dc-element>title</dc-element> <dc-qualifier>alternative</dc-qualifier> <repeatable>true</repeatable> - <label>Outros TÃtulos</label> + <label>Other Titles</label> <input-type>onebox</input-type> - <hint>Se o item possui tÃtulos alternativos, insira-os abaixo.</hint> + <hint>If the item has any alternative titles, please enter them below.</hint> <required></required> </field> @@ -76,12 +76,12 @@ <dc-element>date</dc-element> <dc-qualifier>issued</dc-qualifier> <repeatable>false</repeatable> - <label>Data de Publicação</label> + <label>Date of Issue</label> <input-type>date</input-type> - <hint>Por favor, indique a data de publicação anterior ou distribuição - pública abaixo. Você pode deixar de fora o dia e / ou mês, - se não forem aplicáveis</hint> - <required>Você deve digitar pelo menos o ano.</required> + <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> @@ -89,9 +89,9 @@ <dc-element>publisher</dc-element> <dc-qualifier></dc-qualifier> <repeatable>false</repeatable> - <label>Editora</label> + <label>Publisher</label> <input-type>onebox</input-type> - <hint>Digite o nome da editora que publicou este item anteriormente.</hint> + <hint>Enter the name of the publisher of the previously issued instance of this item.</hint> <required></required> </field> @@ -100,9 +100,9 @@ <dc-element>identifier</dc-element> <dc-qualifier>citation</dc-qualifier> <repeatable>false</repeatable> - <label>Citação</label> + <label>Citation</label> <input-type>onebox</input-type> - <hint>Digite a citação padrão para a publicação anterior deste item</hint> + <hint>Enter the standard citation for the previously issued instance of this item.</hint> <required></required> </field> @@ -111,9 +111,9 @@ <dc-element>relation</dc-element> <dc-qualifier>ispartofseries</dc-qualifier> <repeatable>true</repeatable> - <label>Série/Numero</label> + <label>Series/Report No.</label> <input-type>series</input-type> - <hint>Digite a série e número atribuÃdo a este item pela sua comunidade.</hint> + <hint>Enter the series and number assigned to this item by your community.</hint> <required></required> </field> @@ -123,10 +123,10 @@ <dc-qualifier></dc-qualifier> <!-- An input-type of qualdrop_value MUST be marked as repeatable --> <repeatable>true</repeatable> - <label>Identificadores</label> + <label>Identifiers</label> <input-type value-pairs-name="common_identifiers">qualdrop_value</input-type> - <hint>Se o item tiver quaisquer números ou códigos de identificação associados, -por favor insira os tipos e os números ou códigos reais abaixo.</hint> + <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> @@ -135,9 +135,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>type</dc-element> <dc-qualifier></dc-qualifier> <repeatable>true</repeatable> - <label>Tipo</label> + <label>Type</label> <input-type value-pairs-name="common_types">dropdown</input-type> - <hint>Selecione o(s) tipo (s) de conteúdo do item. Para selecionar mais de um valor na lista, você deve manter pressionada as teclas "CTRL" ou "Shift".</hint> + <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> @@ -146,55 +146,11 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>language</dc-element> <dc-qualifier>iso</dc-qualifier> <repeatable>false</repeatable> - <label>Linguagem</label> + <label>Language</label> <input-type value-pairs-name="common_iso_languages">dropdown</input-type> - <hint>Selecione o idioma do conteúdo principal do item. Se o idioma não aparecer na lista abaixo, selecione "Outro". Se o conteúdo não tem realmente um idioma (por exemplo, se é um conjunto de dados ou uma imagem), por favor selecione 'N/A'.</hint> + <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> - -<!-- ####################################################################################### --> - - <field> - <dc-schema>dc</dc-schema> - <dc-element>description</dc-element> - <dc-qualifier>affiliation</dc-qualifier> - <repeatable>false</repeatable> - <label>Afiliação</label> - <input-type>onebox</input-type> - <hint></hint> - <required></required> - </field> - <field> - <dc-schema>dc</dc-schema> - <dc-element>description</dc-element> - <dc-qualifier>publicationplace</dc-qualifier> - <repeatable>false</repeatable> - <label>Local de Publicação</label> - <input-type>onebox</input-type> - <hint></hint> - <required></required> - </field> - <field> - <dc-schema>dc</dc-schema> - <dc-element>description</dc-element> - <dc-qualifier>edition</dc-qualifier> - <repeatable>false</repeatable> - <label>Edição</label> - <input-type>onebox</input-type> - <hint></hint> - <required></required> - </field> - <field> - <dc-schema>dc</dc-schema> - <dc-element>description</dc-element> - <dc-qualifier>numberofpages</dc-qualifier> - <repeatable>false</repeatable> - <label>Número de páginas</label> - <input-type>onebox</input-type> - <hint></hint> - <required></required> - </field> -<!-- ####################################################################################### --> </page> <page number="2"> @@ -204,9 +160,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-qualifier></dc-qualifier> <!-- An input-type of twobox MUST be marked as repeatable --> <repeatable>true</repeatable> - <label>Assunto e Palavras-chave</label> + <label>Subject Keywords</label> <input-type>twobox</input-type> - <hint>Digite frases ou palavras-chave adequadas abaixo. </hint> + <hint>Enter appropriate subject keywords or phrases below. </hint> <required></required> <vocabulary>srsc</vocabulary> </field> @@ -216,9 +172,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>description</dc-element> <dc-qualifier>abstract</dc-qualifier> <repeatable>false</repeatable> - <label>Resumo</label> + <label>Abstract</label> <input-type>textarea</input-type> - <hint>Digite abaixo o resumo do item. </hint> + <hint>Enter the abstract of the item below. </hint> <required></required> </field> @@ -227,9 +183,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>description</dc-element> <dc-qualifier>sponsorship</dc-qualifier> <repeatable>false</repeatable> - <label>Patrocinadores</label> + <label>Sponsors</label> <input-type>textarea</input-type> - <hint>Digite os nomes dos patrocinadores e/ou códigos de financiamento na caixa abaixo.</hint> + <hint>Enter the names of any sponsors and/or funding codes in the box below. </hint> <required></required> </field> @@ -240,183 +196,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <repeatable>false</repeatable> <label>Description</label> <input-type>textarea</input-type> - <hint>Digite qualquer outra descrição ou comentários abaixo. </hint> + <hint>Enter any other description or comments in this box. </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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <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> - <hint></hint> - <required></required> - </field> -<!-- #######################################################################################3 --> </page> </form> @@ -427,9 +209,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> @@ -569,22 +351,18 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> </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) + "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>Português (Brasil)</displayed-value> - <stored-value>pt_BR</stored-value> + <displayed-value>N/A</displayed-value> + <stored-value></stored-value> </pair> <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 +395,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-solr.properties b/dspace/config/log4j-solr.properties new file mode 100644 index 0000000000000000000000000000000000000000..675d37d43be9c8c5e65fb552dda467cbab8540f3 --- /dev/null +++ b/dspace/config/log4j-solr.properties @@ -0,0 +1,24 @@ +# Logging level +solr.log=logs/ +log4j.rootLogger=INFO, file, CONSOLE + +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender + +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%-4r [%t] %-5p %c %x \u2013 %m%n + +#- size rotation with log cleanup. +log4j.appender.file=org.apache.log4j.DailyRollingFileAppender +# Set this to yyyy-MM-DD for daily log files, or yyyy-MM for monthly files +log4j.appender.file.DatePattern='.'yyyy-MM-dd + +#- File to log to and log format +log4j.appender.file.File=${dspace.dir}/log/solr.log +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d %-5p %c @ %m%n + +log4j.logger.org.apache.zookeeper=WARN +log4j.logger.org.apache.hadoop=WARN + +# set to INFO to enable infostream log messages +log4j.logger.org.apache.solr.update.LoggingInfoStream=OFF 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/rest.cfg b/dspace/config/modules/rest.cfg new file mode 100644 index 0000000000000000000000000000000000000000..0c2dd2af71110bdbfd5e543c7bc256836c1af7d4 --- /dev/null +++ b/dspace/config/modules/rest.cfg @@ -0,0 +1,8 @@ +#---------------------------------------------------------------# +#--------------------REST CONFIGURATIONS------------------------# +#---------------------------------------------------------------# +# These configs are used by the REST module # +#---------------------------------------------------------------# + +# record stats in DSpace statistics module +stats = true \ No newline at end of file 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/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..290be51780800ee55c8706c94fbb4bdc595b7826 100644 --- a/dspace/config/news-xmlui.xml +++ b/dspace/config/news-xmlui.xml @@ -1,36 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> -<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> - </head> - <p> - <i18n:text>participatorio.repo.text</i18n:text> - </p> - </div> - <div id="file.news.div.news" n="news" rend="primary"> - <head> - <i18n:text>participatorio.repo.titleMissao</i18n:text> - </head> - <p> - <i18n:text>participatorio.repo.textMissao</i18n:text> - </p> - </div> - <div id="file.news.div.news" n="news" rend="primary"> - <head> - <i18n:text>participatorio.repo.titleObjetivo</i18n:text> - </head> - <p> - <i18n:text>participatorio.repo.textObjetivo</i18n:text> - </p> - </div> - </body> - <options /> - <meta> - <userMeta /> - <pageMeta /> - <repositoryMeta /> - </meta> +<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>DSpace Repository</head> +<p>DSpace is a digital service that collects, preserves, and distributes digital material. Repositories are important tools for preserving an organization's legacy; they facilitate digital preservation and scholarly communication.</p> +</div> +</body> +<options/> +<meta> +<userMeta/> +<pageMeta/> +<repositoryMeta/> +</meta> </document> diff --git a/dspace/config/registries/dcterms-types.xml b/dspace/config/registries/dcterms-types.xml new file mode 100644 index 0000000000000000000000000000000000000000..17a4eca59a2479dccb5214af5f1883d3dc0d1b7d --- /dev/null +++ b/dspace/config/registries/dcterms-types.xml @@ -0,0 +1,369 @@ +<?xml version="1.0"?> + +<!-- + - dcterms-types.xml + - + - Version: $Revision$ + - + - Date: $Date$ + - + - DCTerms registry contributed to eventually replace dublin-core-types.xml + - + - <dc-type> + - <schema></schema> + - <element></element> + - + - <scope_note></scope_note> + - </dc-type> + --> + +<!-- start of XML --> + +<dspace-dc-types> + + <dspace-header> + <title>DCTerms Types Registry</title> + <contributor.author>Maureen Walsh</contributor.author> + <contributor.author>Sarah Potvin</contributor.author> + <contributor.author>Bram Luyten</contributor.author> + <contributor.editor>$Author$</contributor.editor> + <date.created>$Date$</date.created> + <description>$Log$</description> + <description.version>$Revision$</description.version> + </dspace-header> + + <dc-schema> + <name>dcterms</name> + <namespace>http://purl.org/dc/terms/</namespace> + </dc-schema> + + <dc-type> + <schema>dcterms</schema> + <element>abstract</element> + <scope_note>A summary of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>accessRights</element> + <scope_note>Information about who can access the resource or an indication of its security status. May include information regarding access or restrictions based on privacy, security, or other policies.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>accrualMethod</element> + <scope_note>The method by which items are added to a collection.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>accrualPeriodicity</element> + <scope_note>The frequency with which items are added to a collection.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>accrualPolicy</element> + <scope_note>The policy governing the addition of items to a collection.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>alternative</element> + <scope_note>An alternative name for the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>audience</element> + <scope_note>A class of entity for whom the resource is intended or useful.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>available</element> + <scope_note>Date (often a range) that the resource became or will become available.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>bibliographicCitation</element> + <scope_note>Recommended practice is to include sufficient bibliographic detail to identify the resource as unambiguously as possible.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>comformsTo</element> + <scope_note>An established standard to which the described resource conforms.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>contributor</element> + <scope_note>An entity responsible for making contributions to the resource. Examples of a Contributor include a person, an organization, or a service.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>coverage</element> + <scope_note>The spatial or temporal topic of the resource, the spatial applicability of the resource, or the jurisdiction under which the resource is relevant.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>created</element> + <scope_note>Date of creation of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>creator</element> + <scope_note>An entity primarily responsible for making the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>date</element> + <scope_note>A point or period of time associated with an event in the lifecycle of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>dateAccepted</element> + <scope_note>Date of acceptance of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>dateCopyrighted</element> + <scope_note>Date of copyright.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>dateSubmitted</element> + <scope_note>Date of submission of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>description</element> + <scope_note>An account of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>educationLevel</element> + <scope_note>A class of entity, defined in terms of progression through an educational or training context, for which the described resource is intended.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>extent</element> + <scope_note>The size or duration of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>format</element> + <scope_note>The file format, physical medium, or dimensions of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>hasFormat</element> + <scope_note>A related resource that is substantially the same as the pre-existing described resource, but in another format.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>hasPart</element> + <scope_note>A related resource that is included either physically or logically in the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>hasVersion</element> + <scope_note>A related resource that is a version, edition, or adaptation of the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>identifier</element> + <scope_note>An unambiguous reference to the resource within a given context.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>instructionalMethod</element> + <scope_note>A process, used to engender knowledge, attitudes and skills, that the described resource is designed to support.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isFormatOf</element> + <scope_note>A related resource that is substantially the same as the described resource, but in another format.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isPartOf</element> + <scope_note>A related resource in which the described resource is physically or logically included.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isReferencedBy</element> + <scope_note>A related resource that references, cites, or otherwise points to the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isReplacedBy</element> + <scope_note>A related resource that supplants, displaces, or supersedes the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isRequiredBy</element> + <scope_note>A related resource that requires the described resource to support its function, delivery, or coherence.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>issued</element> + <scope_note>Date of formal issuance (e.g., publication) of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>isVersionOf</element> + <scope_note>A related resource of which the described resource is a version, edition, or adaptation.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>language</element> + <scope_note>A language of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>license</element> + <scope_note>A legal document giving official permission to do something with the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>mediator</element> + <scope_note>An entity that mediates access to the resource and for whom the resource is intended or useful.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>medium</element> + <scope_note>The material or physical carrier of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>modified</element> + <scope_note>Date on which the resource was changed.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>provenance</element> + <scope_note>A statement of any changes in ownership and custody of the resource since its creation that are significant for its authenticity, integrity, and interpretation.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>publisher</element> + <scope_note>An entity responsible for making the resource available.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>references</element> + <scope_note>A related resource that is referenced, cited, or otherwise pointed to by the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>relation</element> + <scope_note>A related resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>replaces</element> + <scope_note>A related resource that is supplanted, displaced, or superseded by the described resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>requires</element> + <scope_note>A related resource that is required by the described resource to support its function, delivery, or coherence.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>rights</element> + <scope_note>Information about rights held in and over the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>rightsHolder</element> + <scope_note>A person or organization owning or managing rights over the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>source</element> + <scope_note>A related resource from which the described resource is derived.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>spatial</element> + <scope_note>Spatial characteristics of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>subject</element> + <scope_note>The topic of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>tableOfContents</element> + <scope_note>A list of subunits of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>temporal</element> + <scope_note>Temporal characteristics of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>title</element> + <scope_note>A name given to the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>type</element> + <scope_note>The nature or genre of the resource.</scope_note> + </dc-type> + + <dc-type> + <schema>dcterms</schema> + <element>valid</element> + <scope_note>Date (often a range) of validity of a resource.</scope_note> + </dc-type> +</dspace-dc-types> diff --git a/dspace/config/spiders/agents/example b/dspace/config/spiders/agents/example new file mode 100644 index 0000000000000000000000000000000000000000..01fa7072c856c323ba93aa6d494ebda816f4a450 --- /dev/null +++ b/dspace/config/spiders/agents/example @@ -0,0 +1,224 @@ +# example spider filter by agent string regular expressions courtesy of OSU Libraries +# https://raw.github.com/osulibraries/DSpace/osukb/dspace/config/Spiders-UserAgent.txt +Alexandria(\s|\+)prototype(\s|\+)project +AllenTrack +Arachmo +Brutus\/AET +China\sLocal\sBrowse\s2\.6 +Code\sSample\sWeb\sClient +ContentSmartz +DSurf +DataCha0s\/2\.0 +Demo\sBot +EmailSiphon +EmailWolf +FDM(\s|\+)1 +Fetch(\s|\+)API(\s|\+)Request +GetRight +Goldfire(\s|\+)Server +Googlebot +HTTrack +LOCKSS +LWP\:\:Simple +MSNBot +Microsoft(\s|\+)URL(\s|\+)Control +Milbot +MuscatFerre +NABOT +NaverBot +Offline(\s|\+)Navigator +OurBrowser +Python\-urllib +Readpaper +Strider +T\-H\-U\-N\-D\-E\-R\-S\-T\-O\-N\-E +Teleport(\s|\+)Pro +Teoma +Wanadoo +Web(\s|\+)Downloader +WebCloner +WebCopier +WebReaper +WebStripper +WebZIP +Webinator +Webmetrics +Wget +Xenu(\s|\+)Link(\s|\+)Sleuth +[+:,\.\;\/\\-]bot +[^a]fish +^voyager\/ +acme\.spider +alexa +almaden +appie +architext +archive\.org_bot +arks +asterias +atomz +autoemailspider +awbot +baiduspider +bbot +biadu +biglotron +bjaaland +blaiz\-bee +bloglines +blogpulse +boitho\.com\-dc +bookmark\-manager +bot +bot[+:,\.\;\/\\-] +bspider +bwh3_user_agent +celestial +cfnetwork|checkbot +combine +commons\-httpclient +contentmatch +core +crawl +crawler +cursor +custo +daumoa +docomo +dtSearchSpider +dumbot +easydl +exabot +fast-webcrawler +favorg +feedburner +feedfetcher\-google +ferret +findlinks +gaisbot +geturl +gigabot +girafabot +gnodspider +google +grub +gulliver +harvest +heritrix +hl_ftien_spider +holmes +htdig +htmlparser +httpget\-5\.2\.2 +httpget\?5\.2\.2 +httrack +iSiloX +ia_archiver +ichiro +iktomi +ilse +internetseer +intute +java +java\/ +jeeves +jobo +kyluka +larbin +libwww +libwww\-perl +lilina +linkbot +linkcheck +linkchecker +linkscan +linkwalker +livejournal\.com +lmspider +lwp +lwp\-request +lwp\-tivial +lwp\-trivial +lycos[_+] +mail.ru +mediapartners\-google +megite +milbot +mimas +mj12bot +mnogosearch +moget +mojeekbot +momspider +motor +msiecrawler +msnbot +myweb +nagios +netcraft +netluchs +ng\/2\. +no_user_agent +nomad +nutch +ocelli +onetszukaj +perman +pioneer +playmusic\.com +playstarmusic\.com +powermarks +psbot +python +qihoobot +rambler +redalert|robozilla +robot +robots +rss +scan4mail +scientificcommons +scirus +scooter +seekbot +seznambot +shoutcast +slurp +sogou +speedy +spider +spiderman +spiderview +sunrise +superbot +surveybot +tailrank +technoratibot +titan +turnitinbot +twiceler +ucsd +ultraseek +urlaliasbuilder +urllib +virus[_+]detector +voila +w3c\-checklink +webcollage +weblayers +webmirror +webreaper +wordpress +worm +xenu +y!j +yacy +yahoo +yahoo\-mmcrawler +yahoofeedseeker +yahooseeker +yandex +yodaobot +zealbot +zeus +zyborg diff --git a/dspace/config/spiders/domains/example b/dspace/config/spiders/domains/example new file mode 100644 index 0000000000000000000000000000000000000000..bf82d6d75aceb3ef1d6bebc1ba96cbe6a1d7c2b4 --- /dev/null +++ b/dspace/config/spiders/domains/example @@ -0,0 +1,12 @@ +# example spider filder by domain regular expressions courtesy of OSU Libraries +# https://raw.github.com/osulibraries/DSpace/osukb/dspace/config/Spiders-DomainName.txt +(.*)\.fastsearch\.net\. +(.*)\.scoutjet\.com\. +(.*)\.yahoo\.com\. +crawl(.*)\.exabot\.com\. +crawl-(.*)-googlebot\.com\. +crawler(.*)\.ask\.com\. +discobot-(.*)\.discoveryengine\.com\. +localhost\. +spider(.*)\.yandex\.ru\. +spider-(.*)\.yandex\.com\. 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/spring/api/requestitem.xml b/dspace/config/spring/api/requestitem.xml new file mode 100644 index 0000000000000000000000000000000000000000..c7e5c6f9ff49f2240677fd29c322decdb22d9f1c --- /dev/null +++ b/dspace/config/spring/api/requestitem.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-2.5.xsd" + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + + <context:annotation-config /> <!-- allows us to use spring annotations in beans --> + + <bean class="org.dspace.app.requestitem.RequestItemMetadataStrategy" + id="org.dspace.app.requestitem.RequestItemAuthorExtractor"> + <!-- + Uncomment these properties if you want lookup in metadata the email and the name of the author to contact for request copy. + If you don't configure that or if the requested item doesn't have these metadata the submitter data are used as fail over + + <property name="emailMetadata" value="schema.element.qualifier" /> + <property name="fullNameMatadata" value="schema.element.qualifier" /> + + --> + </bean> + +</beans> diff --git a/dspace/config/spring/api/sherpa.xml b/dspace/config/spring/api/sherpa.xml new file mode 100644 index 0000000000000000000000000000000000000000..00bf02a2b94f4475beb6329a2ffe23e07f56db8a --- /dev/null +++ b/dspace/config/spring/api/sherpa.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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/ + +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-2.5.xsd" + default-autowire-candidates="*Service,*DAO,javax.sql.DataSource"> + + <context:annotation-config /> <!-- allows us to use spring annotations in beans --> + + <bean class="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService" + id="org.dspace.app.sherpa.submit.SHERPASubmitConfigurationService"> + <property name="issnItemExtractors"> + <list> + <bean class="org.dspace.app.sherpa.submit.MetadataValueISSNExtractor"> + <property name="metadataList"> + <list> + <value>dc.identifier.issn</value> + </list> + </property> + </bean> + <!-- Use the follow if you have the SHERPARoMEOJournalTitle enabled + <bean class="org.dspace.app.sherpa.submit.MetadataAuthorityISSNExtractor"> + <property name="metadataList"> + <list> + <value>dc.title.alternative</value> + </list> + </property> + </bean> --> + </list> + </property> + </bean> + +</beans> diff --git a/dspace/config/xmlui.xconf b/dspace/config/xmlui.xconf index 4a94aaecd568dd78498ee9a0e90cf575d664401b..483f0961832979b0f73b7749e4939416b6d00d4b 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 @@ -171,11 +178,8 @@ <!-- <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/database_schema_3-4.sql b/dspace/etc/oracle/database_schema_3-4.sql new file mode 100644 index 0000000000000000000000000000000000000000..8fcd86fffc35f254a1816f477c1f9761b49e48dc --- /dev/null +++ b/dspace/etc/oracle/database_schema_3-4.sql @@ -0,0 +1,90 @@ +-- +-- database_schema_3-4.sql +-- +-- Version: $Revision$ +-- +-- Date: $Date: 2012-05-29 +-- +-- 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/ +-- + +-- +-- SQL commands to upgrade the database schema of a live DSpace 3.0 or 3.x +-- to the DSpace 4 database schema +-- +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- + +------------------------------------------- +-- Add support for DOIs (table and seq.) -- +------------------------------------------- + +CREATE TABLE Doi +( + doi_id INTEGER PRIMARY KEY, + doi VARCHAR2(256) UNIQUE, + resource_type_id INTEGER, + resource_id INTEGER, + status INTEGER +); + +CREATE SEQUENCE doi_seq; + +-- index by resource id and resource type id +CREATE INDEX doi_resource_id_type_idx ON doi(resource_id, resource_type_id); + +------------------------------------------- +-- Table of running web applications for 'dspace version' -- +------------------------------------------- + +CREATE TABLE Webapp +( + webapp_id INTEGER NOT NULL PRIMARY KEY, + AppName VARCHAR2(32), + URL VARCHAR2(1000), + Started TIMESTAMP, + isUI NUMBER(1) +); + +CREATE SEQUENCE webapp_seq; + +------------------------------------------------------- +-- DS-824 RequestItem table +------------------------------------------------------- + +CREATE TABLE requestitem +( + requestitem_id INTEGER NOT NULL, + token varchar(48), + item_id INDEX, + 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) +); + +CREATE SEQUENCE requestitem_seq; + +------------------------------------------------------- +-- DS-1655 Disable "Initial Questions" page in Submission UI by default +------------------------------------------------------- +update workspaceitem set multiple_titles=1, published_before=1, multiple_files=1; +update workflowitem set multiple_titles=1, published_before=1, multiple_files=1; + +------------------------------------------------------- +-- DS-1811 Removing a collection fails if non-Solr DAO has been used before for item count +------------------------------------------------------- +delete from collection_item_count; +delete from community_item_count; \ No newline at end of file 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/database_schema_3-4.sql b/dspace/etc/postgres/database_schema_3-4.sql new file mode 100644 index 0000000000000000000000000000000000000000..93fe34262cb46c384825dd2a8342d1b476e01ac6 --- /dev/null +++ b/dspace/etc/postgres/database_schema_3-4.sql @@ -0,0 +1,93 @@ +-- +-- database_schema_18-3.sql +-- +-- Version: $Revision$ +-- +-- Date: $Date: 2012-05-29 +-- +-- 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/ +-- + +-- +-- SQL commands to upgrade the database schema of a live DSpace 1.8 or 1.8.x +-- to the DSpace 3 database schema +-- +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. DUMP YOUR DATABASE FIRST. +-- + +------------------------------------------- +-- Add support for DOIs (table and seq.) -- +------------------------------------------- + +CREATE SEQUENCE doi_seq; + +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); + +------------------------------------------- +-- DS-1456 table of currently running webapps +------------------------------------------- + +CREATE SEQUENCE webapp_seq; + +CREATE TABLE Webapp +( + webapp_id INTEGER NOT NULL PRIMARY KEY, + AppName VARCHAR(32), + URL VARCHAR, + Started TIMESTAMP, + isUI INTEGER +); + + +------------------------------------------------------- +-- DS-824 RequestItem table +------------------------------------------------------- + +CREATE SEQUENCE requestitem_seq; + +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) +); + +------------------------------------------------------- +-- DS-1655 Disable "Initial Questions" page in Submission UI by default +------------------------------------------------------- +update workspaceitem set multiple_titles=true, published_before=true, multiple_files=true; +update workflowitem set multiple_titles=true, published_before=true, multiple_files=true; + +------------------------------------------------------- +-- DS-1811 Removing a collection fails if non-Solr DAO has been used before for item count +------------------------------------------------------- +delete from collection_item_count; +delete from community_item_count; \ No newline at end of file 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/rest/pom.xml b/dspace/modules/rest/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..75e287675fde13b2b0d4f17a8810d0a38ff41e44 --- /dev/null +++ b/dspace/modules/rest/pom.xml @@ -0,0 +1,108 @@ +<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.modules</groupId> + <artifactId>rest</artifactId> + <packaging>war</packaging> + <name>DSpace REST (JAX RS 1 - Jersey) :: Local Customizations</name> + <description> + Overlay REST customizations + </description> + + <parent> + <groupId>org.dspace</groupId> + <artifactId>modules</artifactId> + <version>4.1</version> + <relativePath>..</relativePath> + </parent> + + <properties> + <!-- This is the path to the root [dspace-src] directory. --> + <root.basedir>${basedir}/../../..</root.basedir> + </properties> + + <build> + <filters> + <!-- Filter using the properties file defined by dspace-parent POM --> + <filter>${filters.file}</filter> + </filters> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <configuration> + <archiveClasses>false</archiveClasses> + <webResources> + <resource> + <filtering>true</filtering> + <directory>${basedir}/src/main/webapp</directory> + <includes> + <include>WEB-INF/web.xml</include> + </includes> + </resource> + </webResources> + <overlays> + <!-- + the priority of overlays is determined here + 1.) default: anything in the current project has highest + 2.) anything defined here has precedence in the order defined + 3.) any war found transitively in the dependencies will be applied + next. the order is unpredictable. + --> + <overlay> + <groupId>org.dspace</groupId> + <artifactId>dspace-rest</artifactId> + </overlay> + </overlays> + </configuration> + <executions> + <execution> + <phase>prepare-package</phase> + </execution> + </executions> + </plugin> + + </plugins> + </build> + + <profiles> + <profile> + <id>oracle-support</id> + <activation> + <property> + <name>db.name</name> + <value>oracle</value> + </property> + </activation> + <dependencies> + <dependency> + <groupId>com.oracle</groupId> + <artifactId>ojdbc6</artifactId> + </dependency> + </dependencies> + </profile> + </profiles> + + <dependencies> + + <dependency> + <groupId>org.dspace.modules</groupId> + <artifactId>additions</artifactId> + </dependency> + + <!-- DSpace REST Webapp --> + <dependency> + <groupId>org.dspace</groupId> + <artifactId>dspace-rest</artifactId> + <type>war</type> + <version>4.1</version> + </dependency> + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <scope>provided</scope> + </dependency> + + </dependencies> + +</project> diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.js b/dspace/modules/rest/src/main/webapp/.gitignore similarity index 100% rename from dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.js rename to dspace/modules/rest/src/main/webapp/.gitignore 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 deleted file mode 100644 index 9810254b29a739a4f290434412345aea0d9cf9cb..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/i18n/messages.xml +++ /dev/null @@ -1,2295 +0,0 @@ -<?xml version="1.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/ - ---> -<catalogue xml:lang="en" xmlns:i18n="http://apache.org/cocoon/i18n/2.1"> - - <!-- - The format used by all keys is as follows - - xmlui.<Aspect>.<Java Class>.<name> - - There are a few exceptions to this naming format, - 1) Some general keys are in the xmlui.general namespace - because they are used very frequently. - 2) Some general keys which are specific to a particular aspect - may be found at xmlui.<Aspect> without specifying a - particular java class. - --> - - <!-- General keys --> - <message key="xmlui.general.dspace_home">Digital Library Home</message> - <message key="xmlui.general.search">Search</message> - <message key="xmlui.general.go">Go</message> - <message key="xmlui.general.go_home">Go to Digital Library home</message> - <message key="xmlui.general.save">Save</message> - <message key="xmlui.general.cancel">Cancel</message> - <message key="xmlui.general.return">Return</message> - <message key="xmlui.general.update">Update</message> - <message key="xmlui.general.delete">Delete</message> - <message key="xmlui.general.next">Next</message> - <message key="xmlui.general.untitled">Untitled</message> - <message key="xmlui.general.perform">Perform</message> - <message key="xmlui.general.queue">Queue</message> - - <!-- - Page not found keys - - This is a special component that is not part of any aspect but is added - by manakin to all aspect chains. - --> - <message key="xmlui.PageNotFound.title">Page not found</message> - <message key="xmlui.PageNotFound.head">Page not found</message> - <message key="xmlui.PageNotFound.para1">We can't find the page you asked for.</message> - - - <!-- - The "utils" non-aspect - --> - <message key="xmlui.utils.AuthenticationUtil.onlyAdmins">Only site administrators may assume login as another user.</message> - <message key="xmlui.utils.AuthenticationUtil.onlyAuthenticatedAdmins">Only authenticated users who are administrators may assume the login as another user.</message> - <message key="xmlui.utils.AuthenticationUtil.notAnotherAdmin">You may not assume the login as another administrator.</message> - - - <!-- - This section is for feed syndications (RSS, atom, etc) - --> - <message key="xmlui.feed.general_description">The Digital Library repository system captures, stores, indexes, preserves, and distributes digital research material.</message> - <message key="xmlui.feed.header">RSS Feeds</message> - <message key="xmlui.feed.logo_title">The Channel Image</message> - <message key="xmlui.feed.untitled">Untitled</message> - - <!-- - Default notice header - --> - <message key="xmlui.general.notice.default_head">Notice</message> - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - ArtifactBrowser Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- org.dspace.app.xmlui.artifactbrowser.AbstractSearch.java --> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_community">Search Results for Community: {0}</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_collection">Search Results for Collection: {0}</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_none">Search Results</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.result_query">Your query "{0}" produced {1} result(s).</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head2">Communities or Collections matching your query</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head3">Items matching your query</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.no_results">Search produced no results.</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.all_of_dspace">All of Digital Library</message> - - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.title">title</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dateissued">issue date</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dateaccessioned">submit date</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.relevance">relevance</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by">Sort items by</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order">in order</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order.asc">ascending</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order.desc">descending</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.rpp">Results/page</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.AdvancedSearch.java --> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.title">Advanced Search</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.trail">Advanced Search</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.head">Advanced Search</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_scope">Search scope</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_scope_help">Limit your search to a community or collection.</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.conjunction">Conjunction</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_type">Search type</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_for">Search for</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_author">Author</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_title">Title</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_subject">Subject</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_abstract">Abstract</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_series">Series</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_sponsor">Sponsor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_identifier">Identifier</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_language">Language (ISO)</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_keyword">Keyword</message> - - <!-- some common other possibilities for Advanced Search Fields --> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_contributor">Contributor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_creator">Creator</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_subject">Subject</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_description">Description</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_relation">Relation</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_mime">Mime-Type</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_other">Other Contributor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_advisor">Advisor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_department">Department</message> - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_ANY">Full Text</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.and">AND</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.or">OR</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.not">NOT</message> - - - <!-- org.dspace.app.xmlui.artifactbrowser.ConfigureableBrowse.java --> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with">Or enter first few letters:</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with_help">Browse for items that begin with these letters</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_select">Jump to a point in the index:</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_month">(Choose month)</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_year">(Choose year)</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year">Or type in a year: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year_help">Browse for items that are from the given year.</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.no_results">Sorry, there are no results for this browse.</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.sort_by"> Sort by: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.order"> Order: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.rpp"> Results: </message><!-- /Page --> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.etal"> Authors/Item: </message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.etal.all">All</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.title">title</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.dateissued">issue date</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.dateaccessioned">submit date</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.order.asc">ascending</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.order.desc">descending</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.author.column_heading">Authors Name</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.subject.column_heading">Subject</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.metadata.author">Browsing {0} by Author {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.metadata.author">Browsing {0} by Author</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.metadata.subject">Browsing {0} by Subject {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.metadata.subject">Browsing {0} by Subject</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.title">Browsing {0} by Title {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.title">Browsing {0} by Title</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.dateissued">Browsing {0} by Issue Date {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.dateissued">Browsing {0} by Issue Date</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.dateaccessioned">Browsing {0} by Submit Date {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.dateaccessioned">Browsing {0} by Submit Date</message> - - - <!-- org.dspace.app.xmlui.artifactbrowser.CollectionViewer.java --> - <message key="xmlui.ArtifactBrowser.CollectionViewer.search_scope">Search Scope</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.all_of_dspace">All of Digital Library</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.full_text_search">Search within this collection:</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.head_browse">Browse by</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_titles">Titles</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_authors">Authors</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_dates">Dates</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.advanced_search_link">Advanced Search</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.head_recent_submissions">Recent Submissions</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.CommunityBrowser.java --> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.title">Community List</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.trail">Community List</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.head">Communities in Digital Library</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.select">Select a community to browse its collections.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.CommunityViewer.java --> - <message key="xmlui.ArtifactBrowser.CommunityViewer.search_scope">Search Scope</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.all_of_dspace">All of Digital Library</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.full_text_search">Search within this community and its collections:</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_browse">Browse by</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_titles">Titles</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_authors">Authors</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_dates">Dates</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.advanced_search_link">Advanced Search</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_sub_communities">Sub-communities within this community</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_sub_collections">Collections in this community</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_recent_submissions">Recent Submissions</message> - - - <!-- org.dspace.app.xmlui.artifactbrowser.Contact.java --> - <message key="xmlui.ArtifactBrowser.Contact.title">Contact us</message> - <message key="xmlui.ArtifactBrowser.Contact.trail">Contact us</message> - <message key="xmlui.ArtifactBrowser.Contact.head">Contact us</message> - <message key="xmlui.ArtifactBrowser.Contact.para1">{0} administrators may be contacted at:</message> - <message key="xmlui.ArtifactBrowser.Contact.feedback_label">On-line form</message> - <message key="xmlui.ArtifactBrowser.Contact.feedback_link">Feedback</message> - <message key="xmlui.ArtifactBrowser.Contact.email">Email</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.FeedbackForm.java --> - <message key="xmlui.ArtifactBrowser.FeedbackForm.title">Give feedback</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.trail">Give feedback</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.head">Give feedback</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.para1">Thanks for sharing your feedback about our Digital Library system. Your comments are appreciated!</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.email">Your Email</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.email_help">This address will be used to follow up on your feedback.</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.comments">Comments</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.submit">Send Feedback</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.FeedbackSent.java --> - <message key="xmlui.ArtifactBrowser.FeedbackSent.title">Give feedback</message> - <message key="xmlui.ArtifactBrowser.FeedbackSent.trail">Give feedback</message> - <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 in Digital Library</message> - <message key="xmlui.ArtifactBrowser.FrontPageSearch.para1">Enter some text in the box below to search in Digital Library.</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> - <message key="xmlui.ArtifactBrowser.ItemViewer.show_simple">Show simple item record</message> - <message key="xmlui.ArtifactBrowser.ItemViewer.show_full">Show full item record</message> - - <message key="xmlui.ArtifactBrowser.ItemViewer.withdrawn">This item has been withdrawn and is no longer available.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.Navigation.java --> - <message key="xmlui.ArtifactBrowser.Navigation.head_browse">Browse</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_all_of_dspace">All from Digital Library</message> - <message key="xmlui.ArtifactBrowser.Navigation.communities_and_collections">Communities & Collections</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_title">Titles</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_author">Authors</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_subject">Subjects</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_dateissued">By Issue Date</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_dateaccessioned">By Submit Date</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_this_collection">This Collection</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_this_community">This Community</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.SimpleSearch.java --> - <message key="xmlui.ArtifactBrowser.SimpleSearch.title">Search</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.trail">Search</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.head">Search</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.search_scope">Search Scope</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.full_text_search">Full Text Search</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.RestrictedItem.java --> - <message key="xmlui.ArtifactBrowser.RestrictedItem.title">This resource is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.trail">Restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_resource">This resource is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_community">This community is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_collection">This collection is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_item">This item is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_bitstream">This bitstream is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_resource">You do not have the credentials to access the restricted resource.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_community">You do not have the credentials to access the restricted community <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_collection">You do not have the credentials to access the restricted collection <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item">You do not have the credentials to access the restricted item <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_bitstream">You do not have the credentials to access the restricted bitstream <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_collection">collection</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_community">community</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_bitstream">bitstream</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_item">item</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_resource">resource</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.unknown">unknown</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.login">Proceed to login screen</message> - - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_item_withdrawn">This item is withdrawn</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_withdrawn">The selected item is withdrawn and is no longer available.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_restricted_auth">The selected item is access restricted and requires credentials to view. Please login to access the item.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_restricted">Your user account does not have the credentials to view this item. Please contact the system administrator if you have any questions.</message> - - <!-- Authentication messages used at the top of the login page: --> - <message key="xmlui.ArtifactBrowser.RestrictedItem.auth_header">The item is restricted</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.auth_message">The item you are attempting to access is a restricted item and requires credentials to view. Please login below to access the item.</message> - - <message key="xmlui.ArtifactBrowser.StatisticsViewer.choose_month">Monthly Reports</message> - <message key="xmlui.ArtifactBrowser.StatisticsViewer.report.title">Statistical Summary</message> - - <message key="xmlui.ArtifactBrowser.StatisticsViewer.no_report.title">No reports currently available</message> - <message key="xmlui.ArtifactBrowser.StatisticsViewer.no_report.text">There are currently no reports available for this service. Please check back later.</message> - - <!-- Authentication messages used for bitstream authentication --> - <message key="xmlui.BitstreamReader.auth_header">The file is restricted</message> - <message key="xmlui.BitstreamReader.auth_message">The file you are attempting to access is a restricted file and requires credentials to view. Please login below to access the file.</message> - - <!-- Export Archive download messages --> - <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> - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - EPerson Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- General keys used by the EPerson aspect --> - <message key="xmlui.EPerson.trail_new_registration">New user registration</message> - <message key="xmlui.EPerson.trail_forgot_password">Forgot Password</message> - - <!-- org.dspace.app.xmlui.eperson.CannotRegister.java --> - <message key="xmlui.EPerson.CannotRegister.title">Registration unavailable</message> - <message key="xmlui.EPerson.CannotRegister.head">Registration unavailable</message> - <message key="xmlui.EPerson.CannotRegister.para1">The configuration of this Digital Library repository does not allow registration in this context. Please contact the <a href="../contact">site administrator</a> with questions or comments.</message> - - <!-- org.dspace.app.xmlui.eperson.EditProfile.java --> - <message key="xmlui.EPerson.EditProfile.title_update">Update Profile</message> - <message key="xmlui.EPerson.EditProfile.title_create">Create Profile</message> - <message key="xmlui.EPerson.EditProfile.trail_update">Update Profile</message> - <message key="xmlui.EPerson.EditProfile.head_update">Update Profile</message> - <message key="xmlui.EPerson.EditProfile.head_create">Create Profile</message> - <message key="xmlui.EPerson.EditProfile.email_address">Email Address</message> - <message key="xmlui.EPerson.EditProfile.first_name">First Name</message> - <message key="xmlui.EPerson.EditProfile.last_name">Last Name</message> - <message key="xmlui.EPerson.EditProfile.telephone">Contact Telephone</message> - <message key="xmlui.EPerson.EditProfile.Language">Language</message> - <message key="xmlui.EPerson.EditProfile.subscriptions">Subscriptions</message> - <message key="xmlui.EPerson.EditProfile.subscriptions_help">You may subscribe to collections to receive daily e-mail alerts of new items added. You can subscribe to as many or as few collections as you wish. Another alternative to daily e-mail alerts is to use the RSS feeds available for all collections.</message> - <message key="xmlui.EPerson.EditProfile.email_subscriptions">Email Subscriptions</message> - <message key="xmlui.EPerson.EditProfile.select_collection">( Select Collection )</message> - <message key="xmlui.EPerson.EditProfile.update_password_instructions">Optionally, you can enter a new password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.</message> - <message key="xmlui.EPerson.EditProfile.create_password_instructions">Please enter a password in the box below, and confirm it by typing it again into the second box. It should be at least six characters long.</message> - <message key="xmlui.EPerson.EditProfile.password">Password</message> - <message key="xmlui.EPerson.EditProfile.confirm_password">Retype to confirm</message> - <message key="xmlui.EPerson.EditProfile.submit_update">Complete Registration</message> - <message key="xmlui.EPerson.EditProfile.submit_create">Update Profile</message> - <message key="xmlui.EPerson.EditProfile.error_required">This field is required</message> - <message key="xmlui.EPerson.EditProfile.error_invalid_password">Choose a password at least 6 characters long</message> - <message key="xmlui.EPerson.EditProfile.error_unconfirmed_password">Please retype your password to confirm</message> - <message key="xmlui.EPerson.EditProfile.head_auth">Authorization groups you belong to</message> - <message key="xmlui.EPerson.EditProfile.head_identify">Identify</message> - <message key="xmlui.EPerson.EditProfile.head_security">Security</message> - - <!-- org.dspace.app.xmlui.eperson.EPersonUtils.java --> - <message key="xmlui.EPerson.EPersonUtils.register_verify_email">Verify Email</message> - <message key="xmlui.EPerson.EPersonUtils.register_create_profile">Create Profile</message> - <message key="xmlui.EPerson.EPersonUtils.register_finished">Finished</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_verify_email">Verify Email</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_reset_password">Reset Password</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_finished">Finished</message> - - <!-- org.dspace.app.xmlui.eperson.ForgotPasswordFinished.java --> - <message key="xmlui.EPerson.ForgotPasswordFinished.title">Password reset</message> - <message key="xmlui.EPerson.ForgotPasswordFinished.head">Password reset</message> - <message key="xmlui.EPerson.ForgotPasswordFinished.para1">Your password has been reset.</message> - - <!-- org.dspace.app.xmlui.eperson.InvalidToken.java --> - <message key="xmlui.EPerson.InvalidToken.title">Invalid token</message> - <message key="xmlui.EPerson.InvalidToken.trail">Invalid token</message> - <message key="xmlui.EPerson.InvalidToken.head">Invalid token</message> - <message key="xmlui.EPerson.InvalidToken.para1">The URL you provided is invalid. The URL may have been broken across multiple lines in your email client, like this:</message> - <message key="xmlui.EPerson.InvalidToken.para2">If so, copy and paste the entire URL directly into your browser's address bar, rather than simply clicking on the link. The address bar should then contain something like:</message> - - <!-- org.dspace.app.xmlui.eperson.Navigation.java --> - <message key="xmlui.EPerson.Navigation.my_account">My Account</message> - <message key="xmlui.EPerson.Navigation.profile">Profile</message> - <message key="xmlui.EPerson.Navigation.logout">Logout</message> - <message key="xmlui.EPerson.Navigation.login">Login</message> - <message key="xmlui.EPerson.Navigation.register">Register</message> - - <!-- org.dspace.app.xmlui.eperson.PasswordLogin.java --> - <message key="xmlui.EPerson.PasswordLogin.title">Sign in</message> - <message key="xmlui.EPerson.PasswordLogin.trail">Sign in</message> - <message key="xmlui.EPerson.PasswordLogin.head1">Sign in to Digital Library</message> - <message key="xmlui.EPerson.PasswordLogin.title">Sign in</message> - <message key="xmlui.EPerson.PasswordLogin.email_address">E-Mail Address</message> - <message key="xmlui.EPerson.PasswordLogin.error_bad_login">The email address and/or password supplied were not valid.</message> - <message key="xmlui.EPerson.PasswordLogin.password">Password</message> - <message key="xmlui.EPerson.PasswordLogin.forgot_link"> Forgot your password?</message> - <message key="xmlui.EPerson.PasswordLogin.submit">Sign in</message> - <message key="xmlui.EPerson.PasswordLogin.head2">Register new user</message> - <message key="xmlui.EPerson.PasswordLogin.para1">Register an account to subscribe to collections for email updates, and submit new items to this Digital Library.</message> - <message key="xmlui.EPerson.PasswordLogin.register_link">Click here to register.</message> - - <!-- org.dspace.app.xmlui.eperson.LDAPLogin.java --> - <message key="xmlui.EPerson.LDAPLogin.title">Sign in</message> - <message key="xmlui.EPerson.LDAPLogin.trail">Sign in</message> - <message key="xmlui.EPerson.LDAPLogin.head1">Sign in to Digital Library</message> - <message key="xmlui.EPerson.LDAPLogin.title">Sign in</message> - <message key="xmlui.EPerson.LDAPLogin.username">User Name</message> - <message key="xmlui.EPerson.LDAPLogin.error_bad_login">The user name and/or password supplied were not valid.</message> - <message key="xmlui.EPerson.LDAPLogin.password">Password</message> - <message key="xmlui.EPerson.LDAPLogin.submit">Sign in</message> - - <!-- org.dspace.app.xmlui.eperson.LoginChooser.java --> - <message key="xmlui.EPerson.LoginChooser.title">Choose a Login Method</message> - <message key="xmlui.EPerson.LoginChooser.trail">Choose Login</message> - <message key="xmlui.EPerson.LoginChooser.head1">Choose a Login Method</message> - <message key="xmlui.EPerson.LoginChooser.para1">Log in via:</message> - <message key="org.dspace.authenticate.ShibAuthentication.title">Shibboleth Authentication</message> - <message key="org.dspace.eperson.LDAPAuthentication.title">LDAP Authentication</message> - <message key="org.dspace.eperson.PasswordAuthentication.title">Password Authentication</message> - <message key="org.dspace.eperson.X509Authentication.title">Web Certificate Authentication</message> - - <!-- org.dspace.app.xmlui.eperson.FailedAuthentication --> - <message key="xmlui.EPerson.FailedAuthentication.BadCreds">The credentials provided are invalid.</message> - <message key="xmlui.EPerson.FailedAuthentication.BadArgs">Unable to authenticate due to invalid arguments received.</message> - <message key="xmlui.EPerson.FailedAuthentication.NoSuchUser">A user was not found with the credentials provided.</message> - <message key="xmlui.EPerson.FailedAuthentication.title">Authentication Failed</message> - <message key="xmlui.EPerson.FailedAuthentication.trail">Failed Authentication</message> - <message key="xmlui.EPerson.FailedAuthentication.h1">Authentication Failed</message> - - <!-- Login xml files --> - <message key="xmlui.eperson.noAuthMethod.head">No Authentication Method Found</message> - <message key="xmlui.eperson.noAuthMethod.p1">No authentication method was found. Please contact the site administrator.</message> - <message key="xmlui.eperson.shibbLoginFailure.head">Shibboleth Login Failed</message> - <message key="xmlui.eperson.shibbLoginFailure.p1">Shibboleth authentication not available at this time. Please contact the site administrator.</message> - - <!-- org.dspace.app.xmlui.eperson.ProfileUpdated.java --> - <message key="xmlui.EPerson.ProfileUpdated.title">Profile updated</message> - <message key="xmlui.EPerson.ProfileUpdated.trail">Update profile</message> - <message key="xmlui.EPerson.ProfileUpdated.head">Profile updated</message> - <message key="xmlui.EPerson.ProfileUpdated.para1">Your profile information has been updated.</message> - - <!-- org.dspace.app.xmlui.eperson.RegistrationFinished.java --> - <message key="xmlui.EPerson.RegistrationFinished.title">Registration finished</message> - <message key="xmlui.EPerson.RegistrationFinished.head">Registration Finished</message> - <message key="xmlui.EPerson.RegistrationFinished.para1">You're now registered to use the Digital Library system. You can subscribe to collections to receive email updates about new items.</message> - - <!-- org.dspace.app.xmlui.eperson.ResetPassword.java --> - <message key="xmlui.EPerson.ResetPassword.title">Reset password</message> - <message key="xmlui.EPerson.ResetPassword.head">Reset password</message> - <message key="xmlui.EPerson.ResetPassword.para1">Please enter a new password into the box below, and confirm it by typing it again into the second box. It should be at least six characters long.</message> - <message key="xmlui.EPerson.ResetPassword.email_address">Email Address</message> - <message key="xmlui.EPerson.ResetPassword.new_password">New password</message> - <message key="xmlui.EPerson.ResetPassword.confirm_password">Retype to Confirm</message> - <message key="xmlui.EPerson.ResetPassword.submit">Reset password</message> - <message key="xmlui.EPerson.ResetPassword.error_invalid_password">Choose a password at least 6 characters long</message> - <message key="xmlui.EPerson.ResetPassword.error_unconfirmed_password">Please retype your password to confirm</message> - - <!-- org.dspace.app.xmlui.eperson.StartForgotPassword.java --> - <message key="xmlui.EPerson.StartForgotPassword.title">Forgot Password</message> - <message key="xmlui.EPerson.StartForgotPassword.head">Forgot Password</message> - <message key="xmlui.EPerson.StartForgotPassword.para1">Enter the email address you provided when you registered in Digital Library. An email will be sent to that address with further instructions.</message> - <message key="xmlui.EPerson.StartForgotPassword.email_address">Email Address</message> - <message key="xmlui.EPerson.StartForgotPassword.email_address_help">Enter the same address used when registering.</message> - <message key="xmlui.EPerson.StartForgotPassword.error_not_found">Email address not found.</message> - <message key="xmlui.EPerson.StartForgotPassword.submit">Send info</message> - - <!-- org.dspace.app.xmlui.eperson.StartRegistration.java --> - <message key="xmlui.EPerson.StartRegistration.title">New user registration</message> - <message key="xmlui.EPerson.StartRegistration.head1">Email already in use</message> - <message key="xmlui.EPerson.StartRegistration.para1">That email address is already in use by another account. If you want to reset the password for this account, click the reset password button below.</message> - <message key="xmlui.EPerson.StartRegistration.reset_password_for">Reset password for</message> - <message key="xmlui.EPerson.StartRegistration.submit_reset">Reset password</message> - <message key="xmlui.EPerson.StartRegistration.head2">New user registration</message> - <message key="xmlui.EPerson.StartRegistration.para2">Register an account to subscribe to collections for email updates, and submit new items to Digital Library.</message> - <message key="xmlui.EPerson.StartRegistration.email_address">Email Address</message> - <message key="xmlui.EPerson.StartRegistration.email_address_help">This address will be verified and used as your login name.</message> - <message key="xmlui.EPerson.StartRegistration.error_bad_email">Unable to send email to this address.</message> - <message key="xmlui.EPerson.StartRegistration.submit_register">Register</message> - - <!-- org.dspace.app.xmlui.eperson.VerifyEmail.java --> - <message key="xmlui.EPerson.VerifyEmail.title">Verification email sent</message> - <message key="xmlui.EPerson.VerifyEmail.head">Verification email sent</message> - <message key="xmlui.EPerson.VerifyEmail.para">An email has been sent to {0} containing a special URL and further instructions.</message> - - - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Submission Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- general submission aspect messages --> - <message key="xmlui.Submission.general.mydspace_home">MyHome</message> - <message key="xmlui.Submission.general.go_mydspace">Go to MyHome</message> - <message key="xmlui.Submission.general.submission.title">Item submission</message> - <message key="xmlui.Submission.general.submission.trail">Item submission</message> - <message key="xmlui.Submission.general.submission.head">Item submission</message> - <message key="xmlui.Submission.general.submission.previous">< Previous</message> - <message key="xmlui.Submission.general.submission.save">Save & Exit</message> - <message key="xmlui.Submission.general.submission.next">Next ></message> - <message key="xmlui.Submission.general.submission.complete">Complete submission</message> - <message key="xmlui.Submission.general.workflow.title">Item submission</message> - <message key="xmlui.Submission.general.workflow.trail">Item submission</message> - <message key="xmlui.Submission.general.workflow.head">Item submission</message> - <message key="xmlui.Submission.general.showfull">Show full item record</message> - <message key="xmlui.Submission.general.showsimple">Show simple item record</message> - <message key="xmlui.Submission.general.default.title">Submission</message> - <message key="xmlui.Submission.general.default.trail">Submission</message> - - <!-- org.dspace.app.xmlui.submission.CollectiovViewer --> - <message key="xmlui.Submission.CollectionViewer.link1">Submit a new item to this collection</message> - - <!-- org.dspace.app.xmlui.submission.Navigation --> - <message key="xmlui.Submission.Navigation.submissions">Submissions</message> - - - <!-- 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.untitled"><i>Untitled</i></message> - <message key="xmlui.Submission.Submissions.email">email: </message> - <!-- Same transformer, workflow section --> - <message key="xmlui.Submission.Submissions.workflow_head1">Workflow tasks</message> - <message key="xmlui.Submission.Submissions.workflow_info1">These tasks are items that are awaiting approval before they are added to the repository. There are two task queues, one for tasks which you have chosen to accept and another for tasks which have not been taken by anyone yet.</message> - <message key="xmlui.Submission.Submissions.workflow_head2">Tasks you own</message> - <message key="xmlui.Submission.Submissions.workflow_column1"></message> - <message key="xmlui.Submission.Submissions.workflow_column2">Task</message> - <message key="xmlui.Submission.Submissions.workflow_column3">Item</message> - <message key="xmlui.Submission.Submissions.workflow_column4">Collection</message> - <message key="xmlui.Submission.Submissions.workflow_column5">Submitter</message> - <message key="xmlui.Submission.Submissions.workflow_submit_return">Return selected tasks to the pool</message> - <message key="xmlui.Submission.Submissions.workflow_info2">No tasks are assigned to you</message> - <message key="xmlui.Submission.Submissions.workflow_head3">Tasks in the pool</message> - <message key="xmlui.Submission.Submissions.workflow_submit_take">Take selected tasks</message> - <message key="xmlui.Submission.Submissions.workflow_info3">No tasks are in the pool</message> - <!-- Same transformer, submissions section --> - <message key="xmlui.Submission.Submissions.submit_head1">Submissions</message> - <message key="xmlui.Submission.Submissions.submit_info1a">You may </message> - <message key="xmlui.Submission.Submissions.submit_info1b">start a new submission.</message> - <message key="xmlui.Submission.Submissions.submit_info1c">The submission process includes describing the item and uploading the file(s) comprising it. Each community or collection may set its own submission policy.</message> - <message key="xmlui.Submission.Submissions.submit_head2">Unfinished submissions</message> - <message key="xmlui.Submission.Submissions.submit_info2a">These are incomplete item submissions. You may also </message> - <message key="xmlui.Submission.Submissions.submit_info2b">start another submission</message> - <message key="xmlui.Submission.Submissions.submit_info2c">.</message> - <message key="xmlui.Submission.Submissions.submit_column1"></message> - <message key="xmlui.Submission.Submissions.submit_column2">Title</message> - <message key="xmlui.Submission.Submissions.submit_column3">Collection</message> - <message key="xmlui.Submission.Submissions.submit_column4">Submitter</message> - <message key="xmlui.Submission.Submissions.submit_head3">Authoring:</message> - <message key="xmlui.Submission.Submissions.submit_info3">No submissions left unfinished.</message> - <message key="xmlui.Submission.Submissions.submit_head4">Supervising:</message> - <message key="xmlui.Submission.Submissions.submit_submit_remove">Remove selected submissions</message> - <!-- Same transformer, inprogress section --> - <message key="xmlui.Submission.Submissions.progress_head1">Submissions being reviewed</message> - <message key="xmlui.Submission.Submissions.progress_info1">These are your completed submissions which are currently being reviewed by collection curators.</message> - <message key="xmlui.Submission.Submissions.progress_column1">Title</message> - <message key="xmlui.Submission.Submissions.progress_column2">Collection</message> - <message key="xmlui.Submission.Submissions.progress_column3">Status</message> - <!-- Same transformer, workflow status --> - <message key="xmlui.Submission.Submissions.status_0">Submitted</message> - <message key="xmlui.Submission.Submissions.status_1">Awaiting reviewer's attention</message> - <message key="xmlui.Submission.Submissions.status_2">Submission being reviewed</message> - <message key="xmlui.Submission.Submissions.status_3">Awaiting editor's attention</message> - <message key="xmlui.Submission.Submissions.status_4">Submission being edited</message> - <message key="xmlui.Submission.Submissions.status_5">Awaiting final editor's attention</message> - <message key="xmlui.Submission.Submissions.status_6">Submission being edited</message> - <message key="xmlui.Submission.Submissions.status_7">Submission has been archived</message> - <message key="xmlui.Submission.Submissions.status_unknown">Unknown state</message> - <!-- Same transformer, completed submissions section --> - <message key="xmlui.Submission.Submissions.completed.head">Archived Submissions</message> - <message key="xmlui.Submission.Submissions.completed.info">These are your completed submissions which have been accepted into Digital Library.</message> - <message key="xmlui.Submission.Submissions.completed.column1">Date accepted</message> - <message key="xmlui.Submission.Submissions.completed.column2">Title</message> - <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> - <message key="xmlui.Submission.submit.progressbar.access">Access</message> - <message key="xmlui.Submission.submit.progressbar.upload">Upload</message> - <message key="xmlui.Submission.submit.progressbar.verify">Review</message> - <message key="xmlui.Submission.submit.progressbar.creative-commons">Creative Commons</message> - <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> - - <!-- org.dspace.app.xmlui.Submission.submit.ResumeStep --> - <message key="xmlui.Submission.submit.ResumeStep.submit_resume">Resume</message> - - <!-- org.dspace.app.xmlui.Submission.submit.SelectCollection --> - <message key="xmlui.Submission.submit.SelectCollection.head">Select a collection</message> - <message key="xmlui.Submission.submit.SelectCollection.collection">Collection</message> - <message key="xmlui.Submission.submit.SelectCollection.collection_help">Select the collection you wish to submit an item to.</message> - <message key="xmlui.Submission.submit.SelectCollection.collection_default">Select a collection...</message> - - <!-- org.dspace.app.xmlui.Submission.submit.SaveOrRemoveStep --> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.head">Save or cancel your submission?</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.info1">Do you want the submission removed, or do you want to carry on working on it later? You may return to the submission process if you clicked Exit by accident.</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_back">Oops, continue submission</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_save">Save it, I'll work on it later</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_remove">Remove the submission</message> - - - <!-- org.dpspace.app.xmlui.Submission.submit.InitialQuestionsStep --> - <message key="xmlui.Submission.submit.InitialQuestionsStep.head">Initial Questions</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.important_note">Important Note: </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.and"> and </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.separator">, </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.open_set"> (</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.close_set">)</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles">Multiple titles</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles_help">The item has more than one title, <i>e.g. a translated title</i></message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles_note">If the checkbox above is unchecked then the following title(s) will be removed from the item: </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before">Published</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before_help">The item has been published or publicly distributed before</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before_note">If the checkbox above is unchecked then the following will be removed from the item:</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.date_issued">Date Issued</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.citation">Citation</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.publisher">Publisher</message> - - <!-- org.dspace.app.xmlui.Submission.submit.DescribeStep --> - <message key="xmlui.Submission.submit.DescribeStep.head">Describe Item</message> - <message key="xmlui.Submission.submit.DescribeStep.unknown_field">Error: Unknown field type</message> - <message key="xmlui.Submission.submit.DescribeStep.required_field">This field is required</message> - <message key="xmlui.Submission.submit.DescribeStep.last_name_help">Last name, <i>e.g. Smith</i></message> - <message key="xmlui.Submission.submit.DescribeStep.first_name_help">First name(s) + "Jr", <i>e.g. Donald Jr</i></message> - <message key="xmlui.Submission.submit.DescribeStep.year">Year</message> - <message key="xmlui.Submission.submit.DescribeStep.month">Month</message> - <message key="xmlui.Submission.submit.DescribeStep.day">Day</message> - <message key="xmlui.Submission.submit.DescribeStep.series_name">Series Name</message> - <message key="xmlui.Submission.submit.DescribeStep.report_no">Report or paper No.</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.link">Subject Categories</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.title">Subject Categories</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.filter.label">Filter subjects</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.filter.button">Filter</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.loading">Please wait while the controlled vocabulary is loading.</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.error">There was an issue when loading the controlled vocabulary, please try again later.</message> - - - <!-- 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.description">Description</message> - <message key="xmlui.Submission.submit.AccessStep.reason">Reason</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.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.private_settings_help">If selected, the item won't be searchable</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> - <message key="xmlui.Submission.submit.AccessStep.column3">Start Date</message> - <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> - - - <!-- org.dspace.app.xmlui.Submission.submit.EditPolicyStep --> - <message key="xmlui.Submission.submit.EditPolicyStep.head">Edit Policy</message> - - <!-- org.dspace.app.xmlui.Submission.submit.UploadStep --> - <message key="xmlui.Submission.submit.UploadStep.head">Upload File(s)</message> - <message key="xmlui.Submission.submit.UploadStep.file">File</message> - <message key="xmlui.Submission.submit.UploadStep.file_help">Please enter the full path of the file on your computer corresponding to your item. If you click "Browse...", a new window will allow you to select the file from your computer.</message> - <message key="xmlui.Submission.submit.UploadStep.file_error">The item must contain at least one file.</message> - <message key="xmlui.Submission.submit.UploadStep.upload_error">There was a problem uploading your file. Either the filename you entered was incorrect, there was a network problem which prevented the file from reaching us correctly, or you have attempted to upload a file format marked for internal system use only. Please try again.</message> - <message key="xmlui.Submission.submit.UploadStep.virus_error">The file has not been uploaded as it appears to contain a virus. Please contact the system administrator.</message> - <message key="xmlui.Submission.submit.UploadStep.virus_checker_error">A technical problem was encountered whilst attempting to scan the file for viruses. Please contact the system administrator.</message> - <message key="xmlui.Submission.submit.UploadStep.description">File Description</message> - <message key="xmlui.Submission.submit.UploadStep.description_help">Optionally, provide a brief description of the file, for example "<i>Main article</i>", or "<i>Experiment data readings</i>".</message> - <message key="xmlui.Submission.submit.UploadStep.submit_upload">Upload file & add another</message> - <message key="xmlui.Submission.submit.UploadStep.head2">Files Uploaded</message> - <message key="xmlui.Submission.submit.UploadStep.column0">Primary</message> - <message key="xmlui.Submission.submit.UploadStep.column1"> </message> - <message key="xmlui.Submission.submit.UploadStep.column2">File</message> - <message key="xmlui.Submission.submit.UploadStep.column3">Size</message> - <message key="xmlui.Submission.submit.UploadStep.column4">Description</message> - <message key="xmlui.Submission.submit.UploadStep.column5">Format</message> - <message key="xmlui.Submission.submit.UploadStep.column6"></message> - <message key="xmlui.Submission.submit.UploadStep.unknown_name">Unknown</message> - <message key="xmlui.Submission.submit.UploadStep.unknown_format">unknown format</message> - <message key="xmlui.Submission.submit.UploadStep.supported">(Supported)</message> - <message key="xmlui.Submission.submit.UploadStep.known">(Known)</message> - <message key="xmlui.Submission.submit.UploadStep.unsupported">(Unsupported)</message> - <message key="xmlui.Submission.submit.UploadStep.submit_edit">Edit</message> - <message key="xmlui.Submission.submit.UploadStep.checksum">File checksum:</message> - <message key="xmlui.Submission.submit.UploadStep.submit_remove">Remove selected files</message> - - - - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.head">Upload File(s)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file">File</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file_help">Please enter the full path of the file on your computer corresponding to your item. If you click "Browse...", a new window will allow you to select the file from your computer.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file_error">The item must contain at least one file.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.upload_error">There was a problem uploading your file. Either the filename you entered was incorrect, there was a network problem which prevented the file from reaching us correctly, or you have attempted to upload a file format marked for internal system use only. Please try again.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.virus_error">The file has not been uploaded as it appears to contain a virus. Please contact the system administrator.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.virus_checker_error">A technical problem was encountered whilst attempting to scan the file for viruses. Please contact the system administrator.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.description">File Description</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.description_help">Optionally, provide a brief description of the file, for example "<i>Main article</i>", or "<i>Experiment data readings</i>".</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_upload">Upload file & add another</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.head2">Files Uploaded</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column0">Primary</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column1"> </message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column2">File</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column3">Size</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column4">Description</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column5">Format</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column6"></message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unknown_name">Unknown</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unknown_format">unknown format</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.supported">(Supported)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.known">(Known)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unsupported">(Unsupported)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_edit">Edit</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.checksum">File checksum:</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_remove">Remove selected files</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_policy">Policies</message> - - - <!-- org.dspace.app.xmlui.Submission.submit.EditFileStep --> - <message key="xmlui.Submission.submit.EditFileStep.head">Edit File</message> - <message key="xmlui.Submission.submit.EditFileStep.file">File</message> - <message key="xmlui.Submission.submit.EditFileStep.description">File Description</message> - <message key="xmlui.Submission.submit.EditFileStep.description_help">Optionally, provide a brief description of the contents; for example, "<i>Main article</i>", or "<i>Experiment data readings</i>".</message> - <message key="xmlui.Submission.submit.EditFileStep.info1">Select the format of the file from the list below, for example "<i>Adobe PDF</i>" or "<i>Microsoft Word</i>." <strong>If the format is not in the list</strong>, please describe it in the input box below the list.</message> - <message key="xmlui.Submission.submit.EditFileStep.format_detected">Detected Format</message> - <message key="xmlui.Submission.submit.EditFileStep.format_selected">Selected Format</message> - <message key="xmlui.Submission.submit.EditFileStep.format_default">Format not in list</message> - <message key="xmlui.Submission.submit.EditFileStep.info2">If the format is not in the above list, <strong>select "format not in list" above</strong> and describe the file's format in the box below.</message> - <message key="xmlui.Submission.submit.EditFileStep.format_user">Other Format</message> - <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> - - - <!-- org.dspace.app.xmlui.Submission.submit.ReviewStep --> - <message key="xmlui.Submission.submit.ReviewStep.head">Review Submission</message> - <message key="xmlui.Submission.submit.ReviewStep.yes">Yes</message> - <message key="xmlui.Submission.submit.ReviewStep.no">No</message> - <message key="xmlui.Submission.submit.ReviewStep.submit_jump">Correct one of these</message> - <message key="xmlui.Submission.submit.ReviewStep.submit_jump_files">Add or remove a file</message> - <message key="xmlui.Submission.submit.ReviewStep.head1">Initial Questions</message> - <message key="xmlui.Submission.submit.ReviewStep.head2">Describe Page {0}</message> - <message key="xmlui.Submission.submit.ReviewStep.head3">Uploaded Files</message> - <message key="xmlui.Submission.submit.ReviewStep.multiple_titles">Multiple titles</message> - <message key="xmlui.Submission.submit.ReviewStep.published_before">Published before</message> - <message key="xmlui.Submission.submit.ReviewStep.no_metadata">-</message> - <message key="xmlui.Submission.submit.ReviewStep.unknown">unknown</message> - <message key="xmlui.Submission.submit.ReviewStep.known">known</message> - <message key="xmlui.Submission.submit.ReviewStep.supported">supported</message> - - <!-- org.dspace.app.xmlui.Submission.submit.CCLicenseStep --> - <message key="xmlui.Submission.submit.CCLicenseStep.ccws_error">An error occurred ... {0}</message> - <message key="xmlui.Submission.submit.CCLicenseStep.head">License Your Work</message> - <message key="xmlui.Submission.submit.CCLicenseStep.info1">If you wish, you may add a <a href="http://creativecommons.org/">Creative Commons</a> License to your item. <strong>Creative Commons licenses govern what people who read your work may then do with it.</strong></message> - <message key="xmlui.Submission.submit.CCLicenseStep.submit_choose_creative_commons">Choose a license</message> - <message key="xmlui.Submission.submit.CCLicenseStep.submit_to_creative_commons">Proceed to Creative Commons website to select a license</message> - <message key="xmlui.Submission.submit.CCLicenseStep.license">License Type</message> - <message key="xmlui.Submission.submit.CCLicenseStep.select_change">Select or modify your license ...</message> - <message key="xmlui.Submission.submit.CCLicenseStep.no_license">No Creative Commons License</message> - <message key="xmlui.Submission.submit.CCLicenseStep.save_changes">You must click Next to save your changes.</message> - - <!-- org.dspace.app.xmlui.Submission.submit.LicenseStep --> - <message key="xmlui.Submission.submit.LicenseStep.head">Distribution License</message> - <message key="xmlui.Submission.submit.LicenseStep.info1"><strong>There is one last step:</strong> In order for Digital Library to reproduce, translate and distribute your submission worldwide, you must agree to the following terms.</message> - <message key="xmlui.Submission.submit.LicenseStep.info2">Grant the standard distribution license by selecting 'I Grant the License'; and then click 'Complete Submission'.</message> - <message key="xmlui.Submission.submit.LicenseStep.info3">If you have questions regarding this license please contact the system administrators.</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_label">Distribution license</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_checkbox">I Grant the License</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_error">You must grant this license to complete your submission. If you are unable to grant this license at this time you may save your work and return later or remove the submission by clicking the 'Save & Exit' button below.</message> - - <!-- org.dspace.app.xmlui.Submission.submit.RemovedStep --> - <message key="xmlui.Submission.submit.RemovedStep.head">Submission removed</message> - <message key="xmlui.Submission.submit.RemovedStep.info1">Your submission has been cancelled, and the incomplete item removed from the system.</message> - <message key="xmlui.Submission.submit.RemovedStep.go_submission">Go to the Submissions page</message> - - <!-- org.dspace.app.xmlui.Submission.submit.CompletedStep --> - <message key="xmlui.Submission.submit.CompletedStep.head">Submission complete</message> - <message key="xmlui.Submission.submit.CompletedStep.info1">Your submission will now go through the review process for this collection. You will receive e-mail notification as soon as your submission has joined the collection, or if there is a problem with your submission. You may also check on the status of your submission by visiting your submissions page.</message> - <message key="xmlui.Submission.submit.CompletedStep.go_submission">Go to the Submissions page</message> - <message key="xmlui.Submission.submit.CompletedStep.submit_again">Submit another item</message> - - <!-- org.dspace.app.xmlui.Submission.workflow.PerformTaskStep --> - <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_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> - <message key="xmlui.Submission.workflow.PerformTaskStep.commit_help">Once you've edited the item, use this option to commit the item to the archive.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.commit_submit">Commit to archive</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.reject_help">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 resubmit.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.reject_submit">Reject item</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.edit_help">Select this option to change the item's metadata.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.edit_submit">Edit metadata</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.return_help">Return the task to the pool so that another user may perform the task.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.return_submit">Return task to pool</message> - - <!-- org.dspace.app.xmlui.Submission.workflow.RejectTaskStep --> - <message key="xmlui.Submission.workflow.RejectTaskStep.info1">Please enter your reason for rejecting the submission into the box below, indicating whether the submitter may fix a problem and resubmit.</message> - <message key="xmlui.Submission.workflow.RejectTaskStep.reason">Reason</message> - <message key="xmlui.Submission.workflow.RejectTaskStep.reason_required">The reason field is required</message> - <message key="xmlui.Submission.workflow.RejectTaskStep.submit_reject">Reject item</message> - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Administrative Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - <!-- action-generated messages. These are referenced from the sitemap rather than a transformer --> - - <message key="xmlui.administrative.FlowCurationUtils.curate_success_notice">The task was completed successfully.</message> - <message key="xmlui.administrative.FlowCurationUtils.curate_failed_notice">The task exited unexpectedly or failed. For more information, please contact the site administrator or check your system logs.</message> - <message key="xmlui.administrative.FlowCurationUtils.queue_success_notice">The task was queued successfully.</message> - <message key="xmlui.administrative.FlowCurationUtils.queue_failed_notice">The task could not be queued. An error occurred. For more information, please contact the site administrator or check your system logs.</message> - <message key="xmlui.administrative.FlowEPersonUtils.add_eperson_success_notice">The user was added successfully.</message> - <message key="xmlui.administrative.FlowEPersonUtils.edit_eperson_success_notice">The user was edited successfully.</message> - <message key="xmlui.administrative.FlowEPersonUtils.reset_password_success_notice">An email message has been sent to the user containing a token that may be used to choose a new password.</message> - <message key="xmlui.administrative.FlowEPersonUtils.delete_eperson_success_notice">The user(s) were deleted successfully.</message> - <message key="xmlui.administrative.FlowEPersonUtils.delete_eperson_failed_notice">The user(s) listed were not deleted because there are constraints preventing them from being deleted, see the eperson detail page for more information.</message> - <message key="xmlui.administrative.FlowGroupUtils.edit_group_success_notice">The group was edited successfully.</message> - <message key="xmlui.administrative.FlowGroupUtils.delete_group_success_notice">The selected groups were deleted successfully.</message> - <message key="xmlui.administrative.FlowRegistryUtils.add_metadata_schema_success_notice">New schema has been successfully created.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_metadata_schema_success_notice">The schema(s) were successfully deleted.</message> - <message key="xmlui.administrative.FlowRegistryUtils.add_metadata_field_success_notice">Metadata field successfully added.</message> - <message key="xmlui.administrative.FlowRegistryUtils.edit_metadata_field_success_notice">Metadata field successfully edited.</message> - <message key="xmlui.administrative.FlowRegistryUtils.move_metadata_field_success_notice">The field(s) were successfully moved.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_metadata_field_success_notice">The field(s) were successfully deleted.</message> - <message key="xmlui.administrative.FlowRegistryUtils.edit_bitstream_format_success_notice">The format was successfully saved.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_bitstream_format_success_notice">The format(s) were successfully deleted.</message> - <message key="xmlui.administrative.FlowItemUtils.metadata_updated">The item's metadata was successfully updated.</message> - <message key="xmlui.administrative.FlowItemUtils.metadata_added">New metadata was added.</message> - <message key="xmlui.administrative.FlowItemUtils.item_withdrawn">The item has been withdrawn.</message> - <message key="xmlui.administrative.FlowItemUtils.item_reinstated">The item has been reinstated.</message> - <message key="xmlui.administrative.FlowItemUtils.item_moved">The item has been moved.</message> - <message key="xmlui.administrative.FlowItemUtils.item_move_failed">The selected destination collection could not be found.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_added">The new bitstream was successfully uploaded.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_failed">Error while uploading file.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_updated">The bitstream has been updated.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_delete">The selected bitstreams have been deleted.</message> - <message key="xmlui.administrative.FlowMapperUtils.map_items">The items were successfully mapped.</message> - <message key="xmlui.administrative.FlowMapperUtils.unmaped_items">The items have been unmapped.</message> - - <!-- general items for all of the eperson classes --> - <message key="xmlui.administrative.eperson.general.epeople_trail">Manage E-people</message> - - <!-- org.dspace.app.xmlui.administrative.Navigation --> - <!-- contextual menu items --> - <message key="xmlui.administrative.Navigation.context_head">Context</message> - <message key="xmlui.administrative.Navigation.context_edit_item">Edit this item</message> - <message key="xmlui.administrative.Navigation.context_edit_collection">Edit Collection</message> - <message key="xmlui.administrative.Navigation.context_item_mapper">Item Mapper</message> - <message key="xmlui.administrative.Navigation.context_edit_community">Edit Community</message> - <message key="xmlui.administrative.Navigation.context_create_collection">Create Collection</message> - <message key="xmlui.administrative.Navigation.context_create_subcommunity">Create Sub-community</message> - <message key="xmlui.administrative.Navigation.context_create_community">Create Community</message> - <message key="xmlui.administrative.Navigation.context_export_item">Export Item</message> - <message key="xmlui.administrative.Navigation.context_export_collection">Export Collection</message> - <message key="xmlui.administrative.Navigation.context_export_community">Export Community</message> - <message key="xmlui.administrative.Navigation.context_export_metadata">Export Metadata</message> - - <!-- Site administrator options --> - <message key="xmlui.administrative.Navigation.administrative_head">Administrative</message> - <message key="xmlui.administrative.Navigation.administrative_access_control">Access Control</message> - <message key="xmlui.administrative.Navigation.administrative_people">People</message> - <message key="xmlui.administrative.Navigation.administrative_groups">Groups</message> - <message key="xmlui.administrative.Navigation.administrative_authorizations">Authorizations</message> - <message key="xmlui.administrative.Navigation.administrative_registries">Registries</message> - <message key="xmlui.administrative.Navigation.administrative_metadata">Metadata</message> - <message key="xmlui.administrative.Navigation.administrative_format">Format</message> - <message key="xmlui.administrative.Navigation.administrative_items">Items</message> - <message key="xmlui.administrative.Navigation.administrative_withdrawn">Withdrawn Items</message> - <message key="xmlui.administrative.Navigation.administrative_private">Private Items</message> - <message key="xmlui.administrative.Navigation.administrative_control_panel">Control Panel</message> - <message key="xmlui.administrative.Navigation.statistics">Statistics</message> - <message key="xmlui.administrative.Navigation.administrative_import_metadata">Import Metadata</message> - <message key="xmlui.administrative.Navigation.administrative_curation">Curation Tasks</message> - - <!-- my account items --> - <message key="xmlui.administrative.Navigation.account_export">My Exports</message> - - - <!-- export item --> - <message key="xmlui.administrative.ItemExport.head">Export Archive</message> - <message key="xmlui.administrative.ItemExport.item.id.error">The item id provided is invalid.</message> - <message key="xmlui.administrative.ItemExport.collection.id.error">The collection id provided is invalid.</message> - <message key="xmlui.administrative.ItemExport.community.id.error">The community id provided is invalid</message> - <message key="xmlui.administrative.ItemExport.item.not.found">The item requested was not found.</message> - <message key="xmlui.administrative.ItemExport.collection.not.found">The collection requested was not found.</message> - <message key="xmlui.administrative.ItemExport.community.not.found">The community requested was not found.</message> - <message key="xmlui.administrative.ItemExport.item.success">The item was exported successfully. You should receive an e-mail when the archive is ready for download. You can also use the 'My Exports' link to view a list of your available archives.</message> - <message key="xmlui.administrative.ItemExport.collection.success">The collection was exported successfully. You should receive an e-mail when the archive is ready for download. You can also use the 'My Exports' link to view a list of your available archives.</message> - <message key="xmlui.administrative.ItemExport.community.success">The community was exported successfully. You should receive an e-mail when the archive is ready for download. You can also use the 'My Exports' link to view a list of your available archives.</message> - <message key="xmlui.administrative.ItemExport.available.head">Available export archives for download:</message> - - - - <!-- org.dspace.app.xmlui.administrative.eperson.ManageEPeopleMain --> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.title">Manage E-people</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.main_head">E-person management</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_head">Actions</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_create">Create a new E-Person</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_create_link">Click here to add a new E-Person.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_browse">Browse E-People</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_browse_link">Click here to browse all E-People.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_search">Search for E-People</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_help">E-People are searched by any partial match on email or name</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_para1">Below is the list of E-People that matched your search query. Select the E-People you want to delete and click the delete button to continue or click on an E-Person's email or name to edit them.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_head">Search results</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column1"></message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column2">ID</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column3">Name</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column4">Email</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.submit_delete">Delete E-People</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.no_results">Your search found no results...</message> - - - <!-- org.dspace.app.xmlui.administrative.eperson.AddEPersonForm --> - <message key="xmlui.administrative.eperson.AddEPersonForm.title">Add E-Person</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.trail">Add E-Person</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.head1">Create a new user</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.email_taken">That email address is in use by another E-Person. Emails must be unique.</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.head2">New E-Person's information:</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_email_unique">Email address must be unique</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_email">Email address is required</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_fname">First name is required</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_lname">Last name is required</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.req_certs">Require Certificate</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.can_log_in">Can Log In</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.submit_create">Create E-Person</message> - - <!-- org.dspace.app.xmlui.administrative.eperson.EditEPersonForm --> - <message key="xmlui.administrative.eperson.EditEPersonForm.title">Edit E-Person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.trail">Edit E-Person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.head1">Edit an E-Person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.email_taken">That email address is in use by another E-Person. Emails must be unique.</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.head2">{0}'s information:</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_email_unique">Email address must be unique</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_email">Email address is required</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_fname">First name is required</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_lname">Last name is required</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.req_certs">Require Certificate</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.can_log_in">Can Log In</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_reset_password">Reset Password</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.special_help">You may also permanently remove this E-Person from the system or reset his/her password. When resetting a password the user will be sent an email containing a special link they can follow to choose a new password.</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_delete">Delete E-Person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_login_as">Login as E-Person</message> - - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint">This eperson is unable to be deleted because of the following constraint(s):</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.last_conjunction">and</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.item">eperson has submitted one or more items</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.workflowitem">eperson has an active submission workflow</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.tasklistitem">eperson has a workflow task awaiting their attention</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.unknown">eperson has an unidentified constraint within the system</message> - - <message key="xmlui.administrative.eperson.EditEPersonForm.member_head">Groups this E-Person is a member of:</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.indirect_member">(via group: {0})</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.member_none">none</message> - - - <!-- org.dspace.app.xmlui.administrative.eperson.DeleteEPeopleConfirm --> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.title">Confirm E-Person Deletion</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.trail">Confirm Delete</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.confirm_head">Confirm Deletion</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.confirm_para">The following E-People will be deleted: </message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.submit_confirm">Confirm Deletion</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_id">ID</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_name">Name</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_email">Email</message> - - <!-- general items for all of the group classes --> - <message key="xmlui.administrative.group.general.group_trail">Manage Groups</message> - - <!-- org.dspace.app.xmlui.administrative.group.ManageGroupsMain --> - <message key="xmlui.administrative.group.ManageGroupsMain.title">Manage Groups</message> - <message key="xmlui.administrative.group.ManageGroupsMain.main_head">Group management</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_head">Actions</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_create">Create a new group</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_create_link">Click here to add a new Group.</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_browse">Browse groups</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_browse_link">Click here to browse all Groups.</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_search">Search for groups</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_help">Groups are searched by any partial match on their name</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_head">Search results</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column1"></message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column2">ID</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column3">Name</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column4">Members</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column5">Community / Collection</message> - <message key="xmlui.administrative.group.ManageGroupsMain.collection_link">View</message> - <message key="xmlui.administrative.group.ManageGroupsMain.submit_delete">Delete groups</message> - <message key="xmlui.administrative.group.ManageGroupsMain.no_results">Your search found no results...</message> - - <!-- org.dspace.app.xmlui.administrative.group.EditGroupForm --> - <message key="xmlui.administrative.group.EditGroupForm.title">Group Editor</message> - <message key="xmlui.administrative.group.EditGroupForm.trail">Edit group</message> - <message key="xmlui.administrative.group.EditGroupForm.main_head">Group Editor: {0} (id: {1})</message> - <message key="xmlui.administrative.group.EditGroupForm.main_head_new">Group Editor: new group</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_clear">Clear search</message> - <message key="xmlui.administrative.group.EditGroupForm.member">Member</message> - <message key="xmlui.administrative.group.EditGroupForm.cycle">Cycle</message> - <message key="xmlui.administrative.group.EditGroupForm.pending">Pending</message> - <message key="xmlui.administrative.group.EditGroupForm.pending_warn">Note, pending changes are not saved until you click the save button.</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_add">Add</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_remove">Remove</message> - <message key="xmlui.administrative.group.EditGroupForm.collection_para">This group is associated with collection: </message> - <message key="xmlui.administrative.group.EditGroupForm.community_para">This group is associated with community: </message> - <message key="xmlui.administrative.group.EditGroupForm.label_name">Change group name: </message> - <message key="xmlui.administrative.group.EditGroupForm.label_instructions">This group is associated with a specific collection or community and the name cannot be modified.</message> - <message key="xmlui.administrative.group.EditGroupForm.label_search">Search members to add: </message> - <message key="xmlui.administrative.group.EditGroupForm.submit_search_people">E-People...</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_search_groups">Groups...</message> - <message key="xmlui.administrative.group.EditGroupForm.no_results">Your search found no results...</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column2">Name</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column3">Email</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column4"></message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column2">Name</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column3">Members</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column4">Collection</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column5"></message> - <message key="xmlui.administrative.group.ManageGroupsMain.groups_collection_link">view</message> - <message key="xmlui.administrative.group.EditGroupForm.members_head">Members</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column2">Name</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column3">Email</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column4"></message> - <message key="xmlui.administrative.group.EditGroupForm.members_group_name">group: {0}</message> - <message key="xmlui.administrative.group.EditGroupForm.members_none">This group has no members.</message> - <message key="xmlui.administrative.group.EditGroupForm.members_pending">[pending]</message> - <message key="xmlui.administrative.group.EditGroupForm.instructions_para">Remove members</message> - <message key="xmlui.administrative.group.EditGroupForm.collection_link_para">Remove members</message> - - <!-- org.dspace.app.xmlui.administrative.group.DeleteGroupsConfirm --> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.title">Confirm Group Deletion</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.trail">Confirm Delete</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.head">Confirm Deletion</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.para">The following Groups will be deleted:</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column1">ID</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column2">Name</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column3">E-People</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column4">Groups</message> - - <!-- general items for all of the registries classes --> - <message key="xmlui.administrative.registries.general.format_registry_trail">Format registry</message> - <message key="xmlui.administrative.registries.general.metadata_registry_trail">Metadata registry</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.java --> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.title">Delete Bitstream Formats</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.trail">Delete bitstream formats</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.head">Confirm Deletion</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.para1">Are you sure the format should be deleted? Any existing bitstreams of this format will be reverted to the unknown bitstream format.</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column2">MIME Type</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column3">Name</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteMetadataFieldsConfirm.java --> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.title">Delete Fields</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.trail">Delete fields</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.head">Confirm Deletion</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.para1">Are you <b>absolutely</b> sure you want to delete these fields? If any items contain metadata for these fields, the field(s) cannot be deleted. You must ensure that no items use these fields.</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.warning">WARNING: </message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.para2">This will cause an error if any item contains metadata for these fields.</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column2">Name</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column3">Scope Note</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteMetadataSchemaConfirm.java--> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.title">Delete Schema</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.trail">Delete schema</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.head">Confirm Deletion</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.para1">Are you <b>absolutely</b> sure you want to delete this schema? If any items contain metadata for fields contained within this schema, the schema cannot be deleted. You must ensure that no items contain metadata in this schema.</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.warning">WARNING: </message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.para2">This will cause an error if any item contains metadata within this schema.</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column2">Namespace</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column3">Name</message> - - <!-- org.dspace.app.xmlui.administrative.registries.EditBitstreamFormat.java --> - <message key="xmlui.administrative.registries.EditBitstreamFormat.title">Bitstream Format</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.trail">Bitstream format</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.head1">New bitstream format</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.head2">Bitstream format: {0}</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.para1">Provide descriptive metadata about the bitstream format below. While format names must be unique, MIME types do not need to be. You may have separate format registry entries for different versions of Microsoft Word, even though the MIME type will be the same for each of them.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name">Name</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name_help">A unique name for this format, (e.g. Microsoft Word XP or Microsoft Word 2000)</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name_error">The name field is required.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.mimetype">MIME Type</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.mimetype_help">The MIME type associated with this format, does not have to be unique.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.description">Description</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support">Support level</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_help">The level of support your institution pledges for this format.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_0">Unknown</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_1">Known</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_2">Supported</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.internal">Internal</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.internal_help">Formats marked as internal are are hidden from the user, and used for administrative purposes.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.extensions">File extensions</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.extensions_help">Extensions are file extensions that are used to automatically identify the format of uploaded files. You can enter several extensions for each format.</message> - - <!-- org.dspace.app.xmlui.administrative.registries.EditMetadataSchema.java --> - <message key="xmlui.administrative.registries.EditMetadataSchema.title">Metadata Schema</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.trail">Metadata schema</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head1">Metadata Schema: "{0}"</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.para1">This is the metadata schema for "{0}". You may add new or update existing metadata fields to this schema. Fields may also be selected for deletion or be moved to another schema. </message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head2">Schema metadata fields</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column1"></message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column2">ID</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column3">Field</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column4">Scope Note</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.empty">No metadata fields</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_delete">Delete fields</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_move">Move fields to another schema</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head3">Add new metadata field</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.name">Field Name</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.note">Scope Note</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.note_help">Additional notes about this metadata field.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_add">Add new metadata field</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head4">Update Field: {0}</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_update">Update field</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error">Error</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_duplicate_field">The field name is already in use, all element and qualifiers must be unique.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_empty">The field's element is required.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_badchar">The field's element contains a bad character. The element may NOT contain: periods, underscores, or spaces.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_tolong">The field's element is to long, it must be less than 32 characters.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_qualifier_tolong">The field's qualifier is to long, it must be less than 32 characters.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_qualifier_badchar">The field's qualifier contains a bad character. The qualifier may NOT contain: periods, underscores, or spaces.</message> - - <!-- org.dspace.app.xmlui.administrative.registries.FormatRegistryMain.java --> - <message key="xmlui.administrative.registries.FormatRegistryMain.title">Format Registry</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.head">Bitstream format registry</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.para1">This list of bitstream formats provides information about known formats and their support level. You can edit or add new bitstream formats with this tool. Formats marked as 'internal' are hidden from the user, and are used for administrative purposes.</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.new_link">Add a new bitstream format</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column1"></message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column2">ID</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column3">Name</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column4">MIME Type</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column5">Support Level</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.internal">(<i>internal</i>)</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_0">Unknown</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_1">Known</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_2">Support</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.submit_delete">Delete formats</message> - - <!-- org.dspace.app.xmlui.administrative.registries.MetadatRegistryMain.java --> - <message key="xmlui.administrative.registries.MetadataRegistryMain.title">Metadata Registry</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.head1">Metadata registry</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.para1">The metadata registry maintains a list of all metadata fields available in the repository. These fields may be divided amongst multiple schemas. However, DSpace requires the qualified Dublin Core schema. You may extend the Dublin Core schema with additional fields or add new schemas to the registry.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column1"></message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column2">ID</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column3">Namespace</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column4">Name</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.submit_delete">Delete schema</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.head2">Add a new schema</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace">Namespace</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace_help">Namespace should be an established URI location for the new schema.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace_error">This field is required.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name">Name</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name_help">Shorthand notation for the schema. This will be used to prefix a field's name (e.g. dc.element.qualifier). The name must be less than 32 characters and cannot include spaces, periods or underscores.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name_error">This field is required and must be less than 32 characters and cannot contain any spaces, periods, or underscores.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.submit_add">Add new schema</message> - - <!-- org.dspace.app.xmlui.administrative.registries.MoveMetadataField.java --> - <message key="xmlui.administrative.registries.MoveMetadataField.title">Move Fields</message> - <message key="xmlui.administrative.registries.MoveMetadataField.trail">Move fields</message> - <message key="xmlui.administrative.registries.MoveMetadataField.head1">Move metadata fields</message> - <message key="xmlui.administrative.registries.MoveMetadataField.para1">Select a target schema where these fields will be moved. If the target schema already has fields with identical names the fields will not be moved.</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column1">ID</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column2">Name</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column3">Scope Note</message> - <message key="xmlui.administrative.registries.MoveMetadataField.para2">Move to schema: </message> - <message key="xmlui.administrative.registries.MoveMetadataField.submit_move">Move fields</message> - - - - - <!-- general authorization keywords --> - <message key="xmlui.administrative.authorization.general.authorize_trail">Authorization</message> - <message key="xmlui.administrative.authorization.general.policyList_trail">Policy List</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.AuthorizationMain --> - <message key="xmlui.administrative.authorization.AuthorizationMain.title">Administer Authorization Policies</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.main_head">Administer Authorization Policies</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_head">Item authorizations</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.bad_name">The ID you supplied did not resolve to an item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_item_lookup">Look up an item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.search_help">Items may be found by handle or internal ID</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.submit_find">Find</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_advanced">Advanced authorizations tool</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_advanced_link">Click here to go to the item wildcard policy admin tool</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.containerList_head">Community/collection authorizations</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.containerList_para">Click on a community or collection to edit its policies.</message> - - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditContainerPolicies --> - <message key="xmlui.administrative.authorization.EditContainerPolicies.title">Edit Policies</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.trail">Policies List</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_head_collection">Policies for Collection "{0}" ({1},ID: {2})</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_head_community">Policies for Community "{0}" ({1},ID: {2})</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_add_link">Click here to add a new policy. </message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.submit_add">Add</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_id">ID</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_name">Name</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_action">Action</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_group">Group</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_start_date">Start Date</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_end_date">End Date</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.submit_delete">Delete Selected</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.group_edit">Edit</message> - - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditItemPolicies --> - <message key="xmlui.administrative.authorization.EditItemPolicies.title">Edit Item's Policies</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.trail">Policies List</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_head">Policies for Item {0} (ID={1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_para1">With this editor you can view and alter the policies of an item, plus alter policies of individual item components: bundles and bitstreams. Briefly, an item is a container of bundles, and bundles are containers of bitstreams. Containers usually have ADD/REMOVE/READ/WRITE policies, while bitstreams only have READ/WRITE policies.</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_para2">You will notice an extra bundle and bitstream for each item containing the license text for the item.</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_item">Item Policies</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_bundle">Policies for Bundle {0} ({1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_bitstream">Bitstream {0} ({1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_itemPolicy_link">Add a new Item policy</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_bundlePolicy_link">Add a new Bundle policy</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_bitstreamPolicy_link">Add a new Bitstream policy</message> - - <message key="xmlui.administrative.authorization.EditContainerPolicies.no_policies">No policies found for this object.</message> - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditPolicyForm --> - <message key="xmlui.administrative.authorization.EditPolicyForm.title">Edit Policy</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.trail">Edit Policy</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.main_head_new">Create new policy for {0} {1}</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.main_head_edit">Edit policy {0} for {1} {2}</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_no_group">No group selected</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_no_action">No action selected</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column4"></message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column1">ID</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column2">Name</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column3">Actions for this resource</message> - - <message key="xmlui.administrative.authorization.EditPolicyForm.set_group">Set</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.current_group">current</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_head">Search Results</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.policy_currentGroup">Select a group</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_search">Search for a group</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.submit_search_groups">Search</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_action">Select the action</message> - - <message key="xmlui.administrative.authorization.EditPolicyForm.label_name">Name</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_description">Description</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_start_date">Start Date</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_end_date">End Date</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_date_format">Invalid date</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_duplicated_policy">An identical policy for this group and this action is already in place.</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_start_date_greater_than_end_date">Start date is greater than end date</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_date_help">Accepted format: yyyy, yyyy-mm, yyyy-mm-dd</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.AdvacedAuthorizationsForm --> - <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.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> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_collectionSentence">...across the following collections.</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyGroup">Group</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyAction">Action</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyResource">Content Type</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyCollections">Collection</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.submit_add">Add policies</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.submit_remove_all">Clear policies</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.label_date_help">Accepted format: yyyy, yyyy-mm, yyyy-mm-dd</message> - - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_name">Name</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_description">Description</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_start_date">Start Date</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_end_date">End Date</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_date_format">Invalid date</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_start_date_greater_than_end_date">Start date is greater than end date</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_groupIds">Select at least a group</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_collectionIds">Select at least a collection</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.DeletePoliciesConfirm --> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.title">Confirm Policy Deletion</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.trail">Confirm Delete</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.confirm_head">Confirm Deletion</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.confirm_para">The following Policies will be removed: </message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_id">ID</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_action">Action</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_group">Group</message> - - <!-- general edit item messages --> - <message key="xmlui.administrative.item.general.item_trail">Items</message> - <message key="xmlui.administrative.item.general.template_head">Edit Template Item for Collection: {0}</message> - <message key="xmlui.administrative.item.general.option_head">Edit Item</message> - <message key="xmlui.administrative.item.general.option_status">Item Status</message> - <message key="xmlui.administrative.item.general.option_bitstreams">Item Bitstreams</message> - <message key="xmlui.administrative.item.general.option_metadata">Item Metadata</message> - <message key="xmlui.administrative.item.general.option_view">View Item</message> - <message key="xmlui.administrative.item.general.option_curate">Curate</message> - <message key="xmlui.administrative.item.general.option_queue">Queue</message> - - <!-- org.dspace.app.xmlui.administrative.item.AddBitstreamForm --> - <message key="xmlui.administrative.item.AddBitstreamForm.title">Upload Bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.trail">Upload bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.head1">Upload a new bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle_label">Bundle</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.ORIGINAL">Content Files (default)</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.METADATA">Metadata Files</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.THUMBNAIL">Thumbnails</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.LICENSE">Licenses</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.CC-LICENSE">Creative Commons Licenses</message> - <message key="xmlui.administrative.item.AddBitstreamForm.file_label">File</message> - <message key="xmlui.administrative.item.AddBitstreamForm.file_help">Please enter the name of the file on your computer corresponding to your item. If you click "Browse...", a new window will appear in which you can locate and select the file from your computer.</message> - <message key="xmlui.administrative.item.AddBitstreamForm.description_label">Description</message> - <message key="xmlui.administrative.item.AddBitstreamForm.description_help">Optionally, provide a brief description of the file, for example "<i>Main article</i>", or "<i>Experiment data readings</i>".</message> - <message key="xmlui.administrative.item.AddBitstreamForm.submit_upload">Upload</message> - <message key="xmlui.administrative.item.AddBitstreamForm.no_bundles">You need the ADD & WRITE privilege on at least one bundle to be able to upload new bitstreams.</message> - - <!-- org.dspace.app.xmlui.administrative.item.DeleteBitstreamConfirm --> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.title">Confirm Deletion</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.trail">Confirm deletion</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.head1">Confirm Deletion(s)</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.para1">Are you sure you want to delete these bitstreams:</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column1">Name</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column2">Description</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column3">Format</message> - - <!-- org.dspace.app.xmlui.administrative.item.ConfirmItemForm --> - <message key="xmlui.administrative.item.ConfirmItemForm.title">Confirm</message> - <message key="xmlui.administrative.item.ConfirmItemForm.trail">Confirm</message> - <message key="xmlui.administrative.item.ConfirmItemForm.head1">Modify item: {0}</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_delete">Are you sure this item should be completely deleted? Caution: At present, no tombstone would be left.</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_withdraw">Are you sure this item should be withdrawn from the archive?</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_reinstate">Are you sure this item should be reinstated to the archive?</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column1">Field</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column2">Value</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column3">Language</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_withdraw">Withdraw</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_reinstate">Reinstate</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_private">Make it Private</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_public">Make it Public</message> - - <!-- org.dspace.app.xmlui.aspect.administrative.item.MoveItemForm --> - <message key="xmlui.administrative.item.MoveItemForm.title">Move</message> - <message key="xmlui.administrative.item.MoveItemForm.trail">Move</message> - <message key="xmlui.administrative.item.MoveItemForm.head1">Move item: {0}</message> - <message key="xmlui.administrative.item.MoveItemForm.collection">Collection</message> - <message key="xmlui.administrative.item.MoveItemForm.collection_help">Select the collection you wish to move this item to.</message> - <message key="xmlui.administrative.item.MoveItemForm.collection_default">Select a collection...</message> - <message key="xmlui.administrative.item.MoveItemForm.submit_move">Move</message> - <message key="xmlui.administrative.item.MoveItemForm.inherit_policies">Inherit policies</message> - <message key="xmlui.administrative.item.MoveItemForm.inherit_policies_help">Inherit the default policies of the destination collection</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditBitstreamForm --> - <message key="xmlui.administrative.item.EditBitstreamForm.title">Edit Bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.trail">Edit bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.head1">Edit Bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.file_label">File</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_label">Primary bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_option_yes">yes</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_option_no">no</message> - <message key="xmlui.administrative.item.EditBitstreamForm.description_label">Description</message> - <message key="xmlui.administrative.item.EditBitstreamForm.description_help">Optionally, provide a brief description of the file, for example "<i>Main article</i>", or "<i>Experiment data readings</i>"."</message> - <message key="xmlui.administrative.item.EditBitstreamForm.para1">Select the format of the file from the list below, for example "<i>Adobe PDF</i>" or "<i>Microsoft Word</i>", <b>OR</b> if the format is not in the list, please describe it in the box below.</message> - <message key="xmlui.administrative.item.EditBitstreamForm.format_label">Selected Format</message> - <message key="xmlui.administrative.item.EditBitstreamForm.format_default">Format not in list</message> - <message key="xmlui.administrative.item.EditBitstreamForm.para2">If the format is not in the above list, <strong>select "format not in list" above</strong> and describe it in the field below.</message> - <message key="xmlui.administrative.item.EditBitstreamForm.user_label">Other Format</message> - <message key="xmlui.administrative.item.EditBitstreamForm.user_help">The application you used to create the file, and the version number (for example, "<i>ACMESoft SuperApp version 1.5</i>").</message> - <message key="xmlui.administrative.item.EditBitstreamForm.name_label">Filename:</message> - <message key="xmlui.administrative.item.EditBitstreamForm.name_help">Change the filename for this bitstream. Note that this will change the display bitstream URL, but old links will still resolve as long as the sequence ID does not change.</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemBitstreamsForm --> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.title">Item Bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.trail">Item bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.head1">Bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column1"></message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column2">Name</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column3">Description</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column4">Format</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column5">View</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column6">Order</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column7"> </message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.bundle_label"><strong>Bundle: {0}</strong></message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.primary_label"> (primary) </message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.view_link">view</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_add">Upload a new bitstream</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_delete">Delete bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_reorder">Update bitstream order</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.no_upload">You need the ADD & WRITE privilege on the item and bundles to be able to upload new bitstreams.</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.no_remove">Only System Administrators can delete bitstreams / files.</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.previous_order">Previous:</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.order_up">Move up</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.order_down">Move down</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemMetadataForm --> - <message key="xmlui.administrative.item.EditItemMetadataForm.title">Item Metadata</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.trail">Item metadata</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.head1">Add new metadata</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.name_label">Name</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.value_label">Value</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.lang_label">Language</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.submit_add">Add new metadata</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.para1">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.</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.head2">Metadata</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column1">Remove</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column2">Name</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column3">Value</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column4">Language</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemStatusForm --> - <message key="xmlui.administrative.item.EditItemStatusForm.title">Item Status</message> - <message key="xmlui.administrative.item.EditItemStatusForm.trail">Item status</message> - <message key="xmlui.administrative.item.EditItemStatusForm.para1">Welcome to the item management page. From here you can withdraw, reinstate, move or delete the item. You may also update or add new metadata / bitstreams on the other tabs.</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_id">Item Internal ID</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_handle">Handle</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_modified">Last Modified</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_in">In Collections</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_page">Item Page</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_auth">Edit item's authorization policies</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_withdraw">Withdraw item from the repository</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_reinstate">Reinstate item into the repository</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_move">Move item to another collection</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_delete">Completely expunge item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_authorizations">Authorizations...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_withdraw">Withdraw...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_reinstate">Reinstate...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_move">Move...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_delete">Permanently delete</message> - <message key="xmlui.administrative.item.EditItemStatusForm.na">n/a</message> - <message key="xmlui.administrative.item.EditItemStatusForm.sysadmins_only">(system administrators only)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.collection_admins_only">(collection administrators only)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.not_allowed">(you are not allowed to perform this action)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_private">Make item private</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_public">Make item public</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_private">Make it private...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_public">Make it public...</message> - - - - <!-- org.dspace.app.xmlui.administrative.item.ViewItem --> - <message key="xmlui.administrative.item.ViewItem.title">View Item</message> - <message key="xmlui.administrative.item.ViewItem.trail">View Item</message> - <!-- org.dspace.app.xmlui.administrative.item.CurateItemForm.java --> - <message key="xmlui.administrative.item.CurateItemForm.main_head">Curate Item: {0}</message> - <message key="xmlui.administrative.item.CurateItemForm.title">Curate Item</message> - <message key="xmlui.administrative.item.CurateItemForm.trail">Curator</message> - <message key="xmlui.administrative.item.CurateItemForm.label_name">Task</message> - - <!-- org.dspace.app.xmlui.administrative.item.FindItemForm --> - <message key="xmlui.administrative.item.FindItemForm.title">Find Item</message> - <message key="xmlui.administrative.item.FindItemForm.head1">Find Item</message> - <message key="xmlui.administrative.item.FindItemForm.identifier_label">Internal Item ID/Item Handle</message> - <message key="xmlui.administrative.item.FindItemForm.identifier_error">Unable to resolve identifier.</message> - <message key="xmlui.administrative.item.FindItemForm.find">Find</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport --> - <message key="xmlui.administrative.metadataimport.general.title">Import Metadata</message> - <message key="xmlui.administrative.metadataimport.general.head1">Import Metadata</message> - <message key="xmlui.administrative.metadataimport.general.trail">Import Metadata</message> - <message key="xmlui.administrative.metadataimport.general.changes">changes</message> - <message key="xmlui.administrative.metadataimport.general.no_changes">No changes were detected</message> - <message key="xmlui.administrative.metadataimport.general.new_item">New item</message> - <message key="xmlui.administrative.metadataimport.flow.upload_successful">Upload successful</message> - <message key="xmlui.administrative.metadataimport.flow.upload_failed">Upload failed</message> - <message key="xmlui.administrative.metadataimport.flow.upload_badschema">Unknown metadata schema in heading</message> - <message key="xmlui.administrative.metadataimport.flow.upload_badelement">Unknown metadata element in heading</message> - <message key="xmlui.administrative.metadataimport.flow.import_successful">Import successful</message> - <message key="xmlui.administrative.metadataimport.flow.import_failed">Import failed</message> - <message key="xmlui.administrative.metadataimport.flow.over_limit">Number of changes exceeds maximum allowed. Limit changes or alter bulkedit.gui-item-limit in dspace.cfg</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportConfirm --> - <message key="xmlui.administrative.metadataimport.MetadataImportMain.submit_upload">Upload CSV</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportConfirm --> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.success">Successfully processed</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.changes_committed">Changes applied to item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_added">Added: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_removed">Removed: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_newowner">Added to owning collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_oldowner">Removed from owning collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_mapped">Mapped to collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_unmapped">Unmapped from collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_deleted">Item Expunged</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_withdrawn">Item Withdrawn</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_reinstated">Item Reinstated</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportUpload --> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_add">Add: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_remove">Remove: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_newowner">Add to owning collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_oldowner">Remove from owning collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_mapped">Map to collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_unmapped">Un-map from collection</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.changes_pending">Changes pending for item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.submit_confirm">Apply changes</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.hint">Pending changes are listed below for review</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_delete">Expunge Item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_withdraw">Withdraw Item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_reinstate">Reinstate Item</message> - - <!-- general mapper messages --> - <message key="xmlui.administrative.mapper.general.mapper_trail">Item mapper</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.MapperMain --> - <message key="xmlui.administrative.mapper.MapperMain.title">Item Mapper</message> - <message key="xmlui.administrative.mapper.MapperMain.head1">Item Mapper - Map Items from Other Collections</message> - <message key="xmlui.administrative.mapper.MapperMain.para1">Collection: "<strong>{0}</strong>"</message> - <message key="xmlui.administrative.mapper.MapperMain.para2">This is the item mapper tool that allows collection administrators to map items from other collections into this collection. You can search for items from other collections and map them, or browse the list of currently mapped items.</message> - <message key="xmlui.administrative.mapper.MapperMain.stat_label">Statistics</message> - <message key="xmlui.administrative.mapper.MapperMain.stat_info"><strong>{0} of {1}</strong> items in this collection are mapped in from other collections</message> - <message key="xmlui.administrative.mapper.MapperMain.search_label">Search</message> - <message key="xmlui.administrative.mapper.MapperMain.submit_search">Search Items</message> - <message key="xmlui.administrative.mapper.MapperMain.submit_browse">Browse mapped items</message> - <message key="xmlui.administrative.mapper.MapperMain.no_add">(Requires the collection ADD privilege)</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.SearchItemForm --> - <message key="xmlui.administrative.mapper.SearchItemForm.title">Search Items</message> - <message key="xmlui.administrative.mapper.SearchItemForm.trail">Search items</message> - <message key="xmlui.administrative.mapper.SearchItemForm.head1">Search items matching: "{0}"</message> - <message key="xmlui.administrative.mapper.SearchItemForm.submit_map">Map selected items</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column1"></message> - <message key="xmlui.administrative.mapper.SearchItemForm.column2">Collection</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column3">Author</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column4">Title</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.BrowseItemForm --> - <message key="xmlui.administrative.mapper.BrowseItemForm.title">Browse Mapped Items</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.trail">Browse mapped items</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.head1">Browsing mapped items</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.submit_unmap">Unmap selected items</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column1"></message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column2">Collection</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column3">Author</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column4">Title</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.no_remove">You need the REMOVE privilege on this collection to be able to unmap items from this collection.</message> - - <!-- General tags for collection management --> - <message key="xmlui.administrative.collection.general.collection_trail">Collections</message> - <message key="xmlui.administrative.collection.general.options_metadata">Edit Metadata</message> - <message key="xmlui.administrative.collection.general.options_roles">Assign Roles</message> - <message key="xmlui.administrative.collection.general.options_curate">Curate</message> - <message key="xmlui.administrative.collection.general.options_queue">Queue</message> - - <!-- org.dspace.app.xmlui.administrative.collection.AssignCollectionRoles.java --> - <message key="xmlui.administrative.collection.AssignCollectionRoles.title">Edit Collection Roles</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.trail">Roles</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.main_head">Edit Collection: {0}</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.no_role">none</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.create">Create...</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.restrict">Restrict...</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_admins">Collection administrators decide who can submit items to the collection, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization for that collection).</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step1">The people responsible for this step are able to accept or reject incoming submissions. However, they are not able to edit the submission's metadata.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step2">The people responsible for this step are able to edit the metadata of incoming submissions, and then accept or reject them.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step3">The people responsible for this step are able to edit the metadata of incoming submissions, but will not be able to reject them.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_submitters">The E-People and Groups that have permission to submit new items to this collection.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_default_read">E-People and Groups that can read new items submitted to this collection. Changes to this role are not retroactive. Existing items in the system will still be viewable by those who had read access at the time of their addition.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.default_read_custom">This collection uses custom default access settings. </message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.default_read_anonymous">Default read for incoming items and bitstreams is currently set to Anonymous.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.edit_authorization">Edit authorization policies directly.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_name">Role</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_group">Associated group</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_buttons"> </message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_admins">Administrators</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf">Workflow steps</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step1">Accept/Reject Step</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step2">Accept/Reject/Edit Metadata Step</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step3">Edit Metadata Step</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_submitters">Submitters</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_default_read">Default read access</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.sysadmins_only"><nobr>(system administrators only)</nobr></message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.repository_role"><br/>(Repository level group, system administrators only)</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.not_allowed"><nobr>(you are not allowed to configure this)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.collection.CurateCollectionForm.java --> - <message key="xmlui.administrative.collection.CurateCollectionForm.main_head">Curate Collection: {0}</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.title">Curate Collection</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.trail">Curator</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.label_name">Task</message> - - <!-- org.dspace.app.xmlui.administrative.collection.DeleteCollectionConfirm.java --> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.title">Confirm Deletion</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.trail">Confirm</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.main_head">Confirm deletion for collection {0}</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.main_para">Are you sure collection {0} should be deleted? This will delete:</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item1">Any items and incomplete submissions in this collection that aren't contained in other collections</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item2">The contents of those items</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item3">All associated authorization policies</message> - - <!-- org.dspace.app.xmlui.administrative.collection.DeleteCollectionRoleConfirm.java --> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.title">Confirm role deletion</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.trail">Confirm</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_head">Confirm deletion for role {0}</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_para_read">Are you sure you want to delete this role? Deleting this group will give READ access to all users for all items submitted to this collection from now on. Please note that this change is not retroactive. Existing items in the system will still be restricted to the members defined by the role you are about to delete.</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_para">Are you sure you want to delete this role? All changes and customizations made to the {0} group will be lost and would have to be created anew.</message> - - <!-- org.dspace.app.xmlui.administrative.collection.EditCollectionMetadataForm.java --> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.title">Edit Collection Metadata</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.trail">Metadata</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.main_head">Edit Collection: {0}</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_name">Name</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_short_description">Short Description</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_introductory_text">Introductory text (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_copyright_text">Copyright text (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_side_bar_text">News (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_license">License</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_provenance_description">Provenance</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_logo">Upload new logo</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_existing_logo">Current logo</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_item_template">Item template</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_create_template">Create...</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_edit_template">Edit...</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_delete_logo">Remove logo</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_delete">Delete collection</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_save">Save updates</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.sysadmins_only"><nobr>(system administrators only)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.collection.CreateCollectionForm.java --> - <message key="xmlui.administrative.collection.CreateCollectionForm.title">Create Collection</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.trail">Create Collection</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.main_head">Enter Metadata for a New Collection of {0}</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.submit_save">Create</message> - - <!-- General to the harvesting options under collection --> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.title">Collection Harvesting Settings</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail">Harvesting</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest">Content Source</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source">Content source</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal">This is a standard Digital Library collection</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested">This collection harvests its content from an external source</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save">Save</message> - - <!-- org.dspace.app.xmlui.administrative.collection.SetupCollectionHarvestingForm.java --> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.main_settings_head">Harvested Collection Location</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.options_head">Harvesting Options</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_oai_provider">OAI Provider</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_setid">OAI Set id</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_metadata_format">Metadata Format</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaiurl">The url of the target repository's OAI provider service</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaiurl">You must provide a set id of the target collection.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaisetid">The persistent identifier used by the OAI provider to designate the target collection</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaisetid">You must provide a set id of the target collection.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Content being harvested</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Content being harvested</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_only">Harvest metadata only.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_ref">Harvest metadata and references to bitstreams (requires ORE support).</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_bs">Harvest metadata and bitstreams (requires ORE support).</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.submit_test">Test Settings</message> - - <!-- org.dspace.app.xmlui.administrative.collection.EditCollectionHarvestingForm.java --> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.main_settings_head">Harvested Collection Location</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_oai_provider">OAI Provider</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_setid">OAI Set id</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_metadata_format">Metadata format</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_level">Content being harvested</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_result">Last Harvest Result</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_result_new">This collection has not yet been harvested.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_status">Current harvest status</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_ready">Collection ready for harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_busy">Collection is currently being harvested</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_queued">Collection is in queue for harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_oai_error">OAI error occurred during last harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_unknown_error">Unexpected error occurred during last harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_only">Harvest metadata only.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_ref">Harvest metadata and references to bitstreams.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_bs">Harvest metadata and bitstreams (full replication).</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_change_settings">Change Settings</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_import_now">Import Now</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_reimport_collection">Reset and Reimport Collection</message> - - <message key="xmlui.administrative.ControlPanel.option_harvest">Harvesting</message> - <message key="xmlui.administrative.ControlPanel.harvest_scheduler_head">Harvest Scheduler Controls</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_status">Status</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_actions">Actions</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_start">Start Harvester</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_reset">Reset Harvest Status</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_resume">Resume</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_pause">Pause</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_stop">Stop</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_collections">Collections set up for harvesting</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_active">Active harvests</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_queued">Queued harvests</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_errors">OAI errors</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_internal_errors">Internal errors</message> - <message key="xmlui.administrative.ControlPanel.harvest_head_generator_settings">Generator Settings</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_url">OAI-PMH URL</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_source">ORE source</message> - <message key="xmlui.administrative.ControlPanel.harvest_head_harvester_settings">Harvester Settings</message> - - <!-- General tags for community management --> - <message key="xmlui.administrative.community.general.community_trail">Communities</message> - <message key="xmlui.administrative.community.general.options_metadata">Edit Metadata</message> - <message key="xmlui.administrative.community.general.options_roles">Assign Roles</message> - <message key="xmlui.administrative.community.general.options_curate">Curate</message> - <message key="xmlui.administrative.community.general.options_queue">Queue</message> - - <!-- org.dspace.app.xmlui.administrative.community.AssignCommunityRoles.java --> - <message key="xmlui.administrative.community.AssignCommunityRoles.title">Edit Community Roles</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.trail">Roles</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.main_head">Edit Community: {0}</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.no_role">none</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.create">Create...</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.help_admins">Community administrators can create sub-communities or collections, and manage or assign management for those sub-communities or collections. In addition, they decide who can submit items to any sub-collections, edit item metadata (after submission), and add (map) existing items from other collections (subject to authorization).</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.default_read_custom">This community uses custom default access settings. </message> - <message key="xmlui.administrative.community.AssignCommunityRoles.default_read_anonymous">Default read for incoming items and bitstreams is currently set to Anonymous.</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.edit_authorizations">Edit authorization policies directly.</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_name">Role</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_group">Associated group</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_buttons"> </message> - <message key="xmlui.administrative.community.AssignCommunityRoles.label_admins">Administrators</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.sysadmins_only"><nobr>(system administrators only)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.community.CurateCommunityForm.java --> - <message key="xmlui.administrative.community.CurateCommunityForm.main_head">Curate Community: {0}</message> - <message key="xmlui.administrative.community.CurateCommunityForm.title">Curate Community</message> - <message key="xmlui.administrative.community.CurateCommunityForm.trail">Curator</message> - <message key="xmlui.administrative.community.CurateCommunityForm.label_name">Task</message> - - <!-- org.dspace.app.xmlui.administrative.community.DeleteCommunityConfirm.java --> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.title">Confirm Deletion</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.trail">Confirm</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.main_head">Confirm deletion for community {0}</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.main_para">Are you sure community {0} should be deleted? This will delete:</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item1">Any collections in the community that are not contained in other communities</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item2">Any items and incomplete submissions in this community that aren't contained in other communities</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item3">The contents of those items</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item4">All associated authorization policies</message> - - <!-- org.dspace.app.xmlui.administrative.community.DeleteCommunityRoleConfirm.java --> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.title">Confirm role deletion</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.trail">Confirm</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.main_head">Confirm deletion for role {0}</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.main_para">Are you sure you want to delete this role? All changes and customizations made to the {0} group will be lost and would have to be created anew.</message> - - <!-- org.dspace.app.xmlui.administrative.community.EditCommunityMetadataForm.java --> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.title">Edit Community Metadata</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.trail">Metadata</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.main_head">Edit Metadata for Community {0}</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.edit_authorizations">Edit authorization policies</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_name">Name</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_short_description">Short Description</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_introductory_text">Introductory text (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_copyright_text">Copyright text (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_side_bar_text">News (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_logo">Upload new logo</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_existing_logo">Current logo</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.submit_delete_logo">Remove logo</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.submit_delete">Delete community</message> - - <!-- org.dspace.app.xmlui.administrative.community.CreateCommunityForm.java --> - <message key="xmlui.administrative.community.CreateCommunityForm.title">Create Community</message> - <message key="xmlui.administrative.community.CreateCommunityForm.trail">Create Community</message> - <message key="xmlui.administrative.community.CreateCommunityForm.main_head_sub">Enter Metadata for a New Sub-Community of {0}</message> - <message key="xmlui.administrative.community.CreateCommunityForm.main_head_top">Edit Metadata for a New Top-Level Community</message> - <message key="xmlui.administrative.community.CreateCommunityForm.submit_save">Create</message> - - - <!-- org.dspace.app.xmlui.administrative.ControlPanel.java --> - <message key="xmlui.administrative.ControlPanel.title">Control Panel</message> - <message key="xmlui.administrative.ControlPanel.trail">Control panel</message> - <message key="xmlui.administrative.ControlPanel.head">Control Panel</message> - <message key="xmlui.administrative.ControlPanel.option_java">Java Information</message> - <message key="xmlui.administrative.ControlPanel.option_dspace">Digital Library Configuration</message> - <message key="xmlui.administrative.ControlPanel.option_alerts">System-wide Alerts</message> - <message key="xmlui.administrative.ControlPanel.hours">{0} h</message> - <message key="xmlui.administrative.ControlPanel.minutes">{0} m</message> - <message key="xmlui.administrative.ControlPanel.seconds">{0} s</message> - <message key="xmlui.administrative.ControlPanel.java_head">Java and Operating System</message> - <message key="xmlui.administrative.ControlPanel.java_version">Java Runtime Environment Version</message> - <message key="xmlui.administrative.ControlPanel.java_vendor">Java Runtime Environment Vendor</message> - <message key="xmlui.administrative.ControlPanel.os_name">Operating System Name</message> - <message key="xmlui.administrative.ControlPanel.os_arch">Operating System Architecture</message> - <message key="xmlui.administrative.ControlPanel.os_version">Operating System Version</message> - <message key="xmlui.administrative.ControlPanel.runtime_head">Runtime statistics</message> - <message key="xmlui.administrative.ControlPanel.runtime_processors">Available processors</message> - <message key="xmlui.administrative.ControlPanel.runtime_max">Maximum memory</message> - <message key="xmlui.administrative.ControlPanel.runtime_total">Allocated memory</message> - <message key="xmlui.administrative.ControlPanel.runtime_used">Used memory</message> - <message key="xmlui.administrative.ControlPanel.runtime_free">Free memory</message> - <message key="xmlui.administrative.ControlPanel.cocoon_head">Cocoon Info</message> - <message key="xmlui.administrative.ControlPanel.cocoon_version">Cocoon Version</message> - <message key="xmlui.administrative.ControlPanel.cocoon_cache_dir">Cocoon Cache Directory</message> - <message key="xmlui.administrative.ControlPanel.cocoon_work_dir">Cocoon Work Directory</message> - <message key="xmlui.administrative.ControlPanel.cocoon_main_cache_size">Main Cache Size ({0})</message> - <message key="xmlui.administrative.ControlPanel.cocoon_cache_clear">(Clear Cache Immediately)</message> - <message key="xmlui.administrative.ControlPanel.cocoon_persistent_cache_size">Persistent Cache Size ({0})</message> - <message key="xmlui.administrative.ControlPanel.cocoon_transient_cache_size">Transient Cache Size ({0})</message> - <message key="xmlui.administrative.ControlPanel.dspace_head">Digital Library Settings</message> - <message key="xmlui.administrative.ControlPanel.dspace_version">DSpace Version</message> - <message key="xmlui.administrative.ControlPanel.dspace_dir">Digital Library Installation Directory</message> - <message key="xmlui.administrative.ControlPanel.dspace_url">Digital Library Base URL</message> - <message key="xmlui.administrative.ControlPanel.dspace_hostname">Digital Library Host Name</message> - <message key="xmlui.administrative.ControlPanel.dspace_name">Name of the Site</message> - <message key="xmlui.administrative.ControlPanel.db_name">Database Name</message> - <message key="xmlui.administrative.ControlPanel.db_url">Database URL</message> - <message key="xmlui.administrative.ControlPanel.db_driver">JDBC Driver</message> - <message key="xmlui.administrative.ControlPanel.db_maxconnections">Maximum Number of DB Connections in Pool</message> - <message key="xmlui.administrative.ControlPanel.db_maxwait">Max DB Wait Time</message> - <message key="xmlui.administrative.ControlPanel.db_maxidle">Max Idle Connections</message> - <message key="xmlui.administrative.ControlPanel.mail_server">SMTP Mail Server</message> - <message key="xmlui.administrative.ControlPanel.mail_from_address">From E-mail Address</message> - <message key="xmlui.administrative.ControlPanel.mail_feedback_recipient">Feedback Recipient</message> - <message key="xmlui.administrative.ControlPanel.mail_admin">General Site Administration E-mail</message> - <message key="xmlui.administrative.ControlPanel.alerts_head">System-wide Alerts</message> - <message key="xmlui.administrative.ControlPanel.alerts_warning"><strong>Warning for load balanced systems</strong>: System-wide alerts are only effective for the node on which it is activated. You need to ensure that each node in the set receives the activate alert command.</message> - <message key="xmlui.administrative.ControlPanel.alerts_message_label">Alert message</message> - <message key="xmlui.administrative.ControlPanel.alerts_message_default">The system will be going down for regular maintenance. Please save your work and logout.</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_label">Count down</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_none">No count down timer</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_5">5 minutes</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_15">15 minutes</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_30">30 minutes</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_60">1 hour</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_keep">Keep the current count down timer</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_label">Manage session</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_all_sessions">Continue to allow authenticated sessions</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_current_sessions">Restrict authentication but maintain current sessions</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_only_administrative_sessions">Restrict authentication and kill current sessions</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_note"><strong>Note:</strong> Site administrators are exempt from session management.</message> - <message key="xmlui.administrative.ControlPanel.alerts_submit_activate">Activate</message> - <message key="xmlui.administrative.ControlPanel.alerts_submit_deactivate">Deactivate</message> - <message key="xmlui.administrative.ControlPanel.activity_head">Current Activity ({0} pages maximum)</message> - <message key="xmlui.administrative.ControlPanel.stop_anonymous">STOP recording anonymous activity.</message> - <message key="xmlui.administrative.ControlPanel.start_anonymous">START recording anonymous activity.</message> - <message key="xmlui.administrative.ControlPanel.stop_bot">STOP recording bot activity.</message> - <message key="xmlui.administrative.ControlPanel.start_bot">START recording bot activity.</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_time">Time Stamp</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_user">User</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_ip">IP address</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_url">URL Page</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_Agent">User-Agent</message> - <message key="xmlui.administrative.ControlPanel.activity_anonymous">Anonymous {0}</message> - <message key="xmlui.administrative.ControlPanel.activity_none">No page views have been recorded.</message> - - <message key="xmlui.administrative.ControlPanel.select_panel">Use the tabs above to select the information to display</message> - - <!-- org.dspace.app.xmlui.administrative.SystemwideAlerts --> - <message key="xmlui.administrative.SystemwideAlerts.countdown"><strong>In {0} minutes</strong>: </message> - - <!-- org.dspace.app.xmlui.administrative.NotAuthorized --> - <message key="xmlui.administrative.NotAuthorized.title">Not Authorized</message> - <message key="xmlui.administrative.NotAuthorized.trail">Not authorized</message> - <message key="xmlui.administrative.NotAuthorized.head">Insufficient privileges</message> - <message key="xmlui.administrative.NotAuthorized.para1a">Your account has insufficient privileges to perform the requested action. If you feel this is an error or have questions about your privileges, please contact the site's </message> - <message key="xmlui.administrative.NotAuthorized.para1b">system administrators</message> - <message key="xmlui.administrative.NotAuthorized.para1c">.</message> - <message key="xmlui.administrative.NotAuthorized.para2">Login as another user</message> - - <!-- System-wide Curation Tasks form (org.dspace.app.xmlui.aspect.administrative.CurateForm) --> - <message key="xmlui.administrative.CurateForm.title">System Curation Tasks</message> - <message key="xmlui.administrative.CurateForm.trail">Curation Tasks</message> - <message key="xmlui.administrative.CurateForm.object_label_name">Handle of Digital Library Object</message> - <message key="xmlui.administrative.CurateForm.object_hint">Hint: Enter [your-handle-prefix]/0 to run a task across entire site (not all tasks may support this capability)</message> - <message key="xmlui.administrative.CurateForm.task_label_name">Task</message> - <!-- Used by Curate<DSO>Form classes also --> - <message key="xmlui.administrative.CurateForm.taskgroup_label_name">Choose from the following groups</message> - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Statistics Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - <message key="xmlui.statistics.title">Statistics</message> - <message key="xmlui.statistics.search.title">Search Statistics</message> - <message key="xmlui.statistics.search.head">Search Statistics</message> - <message key="xmlui.statistics.search.head-dso">Search Statistics for {0}</message> - <message key="xmlui.statistics.search.error">There was an error while generating the search statistics, please try again later.</message> - <message key="xmlui.statistics.search.no-results">No search statistics available for the selected period.</message> - <message key="xmlui.statistics.workflow.title">Workflow Statistics</message> - <message key="xmlui.statistics.visits.total">Total Visits</message> - <message key="xmlui.statistics.visits.month">Total Visits Per Month</message> - <message key="xmlui.statistics.visits.views">Views</message> - <message key="xmlui.statistics.visits.countries">Top country views</message> - <message key="xmlui.statistics.visits.cities">Top cities views</message> - <message key="xmlui.statistics.visits.bitstreams">File Visits</message> - <message key="xmlui.statistics.Navigation.title">Statistics</message> - <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-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> - <message key="xmlui.statistics.workflow.error">There was an error while generating the workflow statistics, please try again later.</message> - <message key="xmlui.statistics.workflow.head">Workflow Statistics</message> - <message key="xmlui.statistics.workflow.head-dso">Workflow Statistics for {0}</message> - - - <message key="xmlui.statistics.StatisticsSearchTransformer.search-terms.head">Top Search Terms</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.search-total.head">Total</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-month">Previous month</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-6-months">Previous 6 months</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-year">Previous year</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.overall">Overall</message> - - - <message key="xmlui.statistics.display.table.column-label.search-terms">Search Term</message> - <message key="xmlui.statistics.display.table.column-label.searches">Searches</message> - <message key="xmlui.statistics.display.table.column-label.percent-total">% of Total</message> - <message key="xmlui.statistics.display.table.column-label.views-search">Pageviews / Search</message> - <message key="xmlui.statistics.display.table.column-label.step">Step</message> - <message key="xmlui.statistics.display.table.column-label.performed">Performed</message> - <message key="xmlui.statistics.display.table.column-label.average">Average</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP1POOL">Accept/Reject Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP1">Accept/Reject Step</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP2POOL">Accept/Reject/Edit Metadata Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP2">Accept/Reject/Edit Metadata Step</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP3POOL">Edit Metadata Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP3">Edit Metadata Step</message> - <message key="xmlui.statistics.display.table.workflow.step.default.reviewstep.claimaction">Accept/Reject Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.default.reviewstep.reviewaction">Accept/Reject Step</message> - <message key="xmlui.statistics.display.table.workflow.step.default.editstep.claimaction">Accept/Reject/Edit Metadata Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.default.editstep.editaction">Accept/Reject/Edit Metadata Step</message> - <message key="xmlui.statistics.display.table.workflow.step.default.finaleditstep.claimaction">Edit Metadata Step Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.default.finaleditstep.finaleditaction">Edit Metadata Step</message> - <message key="xmlui.statistics.display.table.workflow.step.default.finaleditstep.finaleditaction">Edit Metadata Step</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.scoreReviewStep.claimaction">Score Review Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.scoreReviewStep.scorereviewaction">Score Review</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.evaluationStep.evaluationaction">Score Review Evaluation</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.evaluationStep.noUserSelectionAction">Score Review Evaluation Configuration</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.selectReviewerStep.claimaction">Single User Review Pool</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.singleUserReviewStep.autoassignAction">Single User Auto Assign Action</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.singleUserReviewStep.singleuserreviewaction">Single User Review Action</message> - - - - - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - dri2xhtml - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - <!-- structural.xsl --> - <message key="xmlui.dri2xhtml.structural.footer-promotional"> - <a href="http://di.tamu.edu" id="ds-logo-link"> - <span id="ds-footer-logo"> </span> - </a> - <p> - This website is using Manakin, a new front end for DSpace created by Texas A&M University - Libraries. The interface can be extensively modified through Manakin Aspects and XSL based Themes. - For more information visit - <a href="http://di.tamu.edu">http://di.tamu.edu</a> and - <a href="http://dspace.org">http://dspace.org</a> - </p> - </message> - <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.profile">Profile: </message> - <message key="xmlui.dri2xhtml.structural.logout">Logout</message> - <message key="xmlui.dri2xhtml.structural.login">Login</message> - - <message key="xmlui.dri2xhtml.structural.search">Search Digital Library</message> - <message key="xmlui.dri2xhtml.structural.search-advanced">Advanced Search</message> - <message key="xmlui.dri2xhtml.structural.search-in-community">This Community</message> - <message key="xmlui.dri2xhtml.structural.search-in-collection">This Collection</message> - - <message key="xmlui.dri2xhtml.structural.pagination-previous">Previous Page</message> - <message key="xmlui.dri2xhtml.structural.pagination-info">Now showing items {0}-{1} of {2}</message> - <message key="xmlui.dri2xhtml.structural.pagination-next">Next Page</message> - - <message key="xmlui.dri2xhtml.structural.link_cc">Creative Commons</message> - <message key="xmlui.dri2xhtml.structural.link_original_license">Original License</message> - - - <!-- DS-METS-1.0-MODS.xsl --> - <!-- DS-METS-1.0-DIM.xsl --> - <!-- DS-METS-1.0-QDC.xsl --> - <message key="xmlui.dri2xhtml.METS-1.0.no-preview">No preview available</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-title">Untitled</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-author">Unknown author</message> - <message key="xmlui.dri2xhtml.METS-1.0.non-conformant"> - This is not a DSpace object conformant to the METS 1.0 profile and as such cannot be - rendered effectively. You can override either the template that handles the general - case in dri2xhtml to perform the needed function, or create your template to match - whatever profile you use. - </message> - - <message key="xmlui.dri2xhtml.METS-1.0.item-preview">Preview</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-title">Title</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-author">Author</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-abstract">Abstract</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-description">Description</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-uri">URI</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-date">Date</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-publisher">Publisher</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-subject">Subject</message> - - <message key="xmlui.dri2xhtml.METS-1.0.item-files-head">Files in this item</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-file">Files</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-name">Name</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-size">Size</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-format">Format</message> - <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-no-files">There are no files associated with this item.</message> - - <message key="xmlui.dri2xhtml.METS-1.0.size-bytes">bytes</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-kilobytes">Kb</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-megabytes">Mb</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-gigabytes">Gb</message> - - <message key="xmlui.dri2xhtml.METS-1.0.license-text">The following license files are associated with this item:</message> - <message key="xmlui.dri2xhtml.METS-1.0.cc-license-text">Except where otherwise noted, this item's license is described as </message> - - <message key="xmlui.dri2xhtml.METS-1.0.collection-not-implemented"> - The summaryView of a collection is not currently used or implemented. This can be fixed - by overriding the dri2xhtml's template named collectionSummaryView. - </message> - <message key="xmlui.dri2xhtml.METS-1.0.community-not-implemented"> - The summaryView of a community is not currently used or implemented. This can be fixed - by overriding the dri2xhtml's template named communitySummaryView. - </message> - - <message key="xmlui.dri2xhtml.METS-1.0.collection-logo-alt">The collection's logo</message> - <message key="xmlui.dri2xhtml.METS-1.0.community-logo-alt">The community's logo</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-logo-alt">No logo</message> - <message key="xmlui.dri2xhtml.METS-1.0.news">News</message> - - <!-- Internationalization elements specific to the Qualified Dublin Core metadata handler. - DS-METS-1.0-QDC.xsl --> - <message key="xmlui.dri2xhtml.METS-1.0.qdc-not-applicable"> - Qualified Dublin Core (QDC) is not applicable to Digital Library communities and collections at - this time. When using QDC, you should use the QDC crosswalk for Digital Library items and either - DIM or MODS for processing of communities and collections. - </message> - - <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> - - - <!-- Special pioneer model related text, wherever it might end up --> - <message key="xmlui.dri2xhtml.pioneer.preview">Preview</message> - <message key="xmlui.dri2xhtml.pioneer.date">Date</message> - <message key="xmlui.dri2xhtml.pioneer.title">Title</message> - <message key="xmlui.dri2xhtml.pioneer.author">Author</message> - - <!-- tag used to handle the empty textarea tag added 09/28/2006 --> - <message key="xmlui.dri2xhtml.default.textarea.value"> </message> - - <!--###### File Format MIME Type Mappings ######--> - - <!-- Application-based formats --> - <message key="xmlui.dri2xhtml.mimetype.application/marc">MARC record</message> - <message key="xmlui.dri2xhtml.mimetype.application/mathematica">Mathematica</message> - <message key="xmlui.dri2xhtml.mimetype.application/msword">Microsoft Word</message> - <message key="xmlui.dri2xhtml.mimetype.application/octet-stream">Unknown</message> - <message key="xmlui.dri2xhtml.mimetype.application/pdf">PDF</message> - <message key="xmlui.dri2xhtml.mimetype.application/postscript">Postscript</message> - <message key="xmlui.dri2xhtml.mimetype.application/sgml">SGML</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-excel">Microsoft Excel</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-powerpoint">Microsoft PowerPoint</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-project">Microsoft Project</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.database">OpenOffice Base</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.formula">OpenOffice Math</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.graphics">OpenOffice Draw</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.presentation">OpenOffice Impress</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.spreadsheet">OpenOffice Calc</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.text">OpenOffice Writer</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.presentationml.presentation">Microsoft PowerPoint 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">Microsoft Excel 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.wordprocessingml.document">Microsoft Word 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.calc">OpenOffice Calc (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.draw">OpenOffice Draw (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.impress">OpenOffice Impress (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.writer.global">OpenOffice Writer (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.visio">Microsoft Visio</message> - <message key="xmlui.dri2xhtml.mimetype.application/wordperfect5.1">WordPerfect</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-dvi">TeX DVI</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-filemaker">FileMaker Pro</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-java-applet">Java applet</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-latex">LaTeX</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-photoshop">Photoshop</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-tex">TeX</message> - - <!-- Audio-based formats --> - <message key="xmlui.dri2xhtml.mimetype.audio/basic">Basic Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/flac">FLAC Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/m4a">AAC audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/m4a-latm">AAC audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/mpeg">mp3 audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-aiff">AIFF audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-mpeg">MPEG Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ms-wma">WMA Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ms-wmv">WMV Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ogg">Ogg Vorbis</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-pn-realaudio">RealAudio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-wav">WAV audio</message> - - <!-- Image-based formats --> - <message key="xmlui.dri2xhtml.mimetype.image/gif">GIF image</message> - <message key="xmlui.dri2xhtml.mimetype.image/jp2">JPEG 2000 image</message> - <message key="xmlui.dri2xhtml.mimetype.image/jpeg">JPEG image</message> - <message key="xmlui.dri2xhtml.mimetype.image/png">PNG image</message> - <message key="xmlui.dri2xhtml.mimetype.image/tiff">TIFF image</message> - <message key="xmlui.dri2xhtml.mimetype.image/x-ms-bmp">BMP image</message> - <message key="xmlui.dri2xhtml.mimetype.image/x-photo-cd">Photo CD</message> - - <!-- Text-based formats --> - <message key="xmlui.dri2xhtml.mimetype.text/css">CSS file</message> - <message key="xmlui.dri2xhtml.mimetype.text/csv">CSV file</message> - <message key="xmlui.dri2xhtml.mimetype.text/html">HTML</message> - <message key="xmlui.dri2xhtml.mimetype.text/javascript">Javascript</message> - <message key="xmlui.dri2xhtml.mimetype.text/plain">Text file</message> - <message key="xmlui.dri2xhtml.mimetype.text/richtext">RTF file</message> - <message key="xmlui.dri2xhtml.mimetype.text/xml">XML</message> - - <!-- Video-based formats --> - <message key="xmlui.dri2xhtml.mimetype.video/avi">AVI video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mjp2">Motion JPEG 2000</message> - <message key="xmlui.dri2xhtml.mimetype.video/mpeg">MPEG video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mpeg2">MPEG-2 video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mp4">MPEG-4 video</message> - <message key="xmlui.dri2xhtml.mimetype.video/quicktime">QuickTime video</message> - - <!-- explanatory messages for choice authority confidence values --> - <message key="xmlui.authority.confidence.description.cf_unset">Confidence was never recorded for this value</message> - <message key="xmlui.authority.confidence.description.cf_novalue">No reasonable confidence value was returned from the authority</message> - <message key="xmlui.authority.confidence.description.cf_rejected">The authority recommends this submission be rejected</message> - <message key="xmlui.authority.confidence.description.cf_failed">The authority encountered an internal failure</message> - <message key="xmlui.authority.confidence.description.cf_notfound">There are no matching answers in the authority</message> - <message key="xmlui.authority.confidence.description.cf_ambiguous">There are multiple matching authority values of equal validity</message> - <message key="xmlui.authority.confidence.description.cf_uncertain">Value is singular and valid but has not been seen and accepted by a human so it is still uncertain</message> - <message key="xmlui.authority.confidence.description.cf_accepted">This authority value has been confirmed as accurate by an interactive user</message> - <!-- help message on "unlock" button in EditItemMetadata display --> - <message key="xmlui.authority.confidence.unlock.help">Unlock the authority key value for manual editing, or toggle it locked again</message> - - <!-- Choice Lookup popup window --> - <!-- NOTE: These messages necessarily use a *different* format for - - parameters, unfortunately, since substitution happens in the - - JavaScript (AJAX) that completes the lookup popup window. - - So, positional parameters are @1@, @2@, etc. - --> - <message key="xmlui.ChoiceLookupTransformer.title">Digital Library Value Lookup</message> - <message key="xmlui.ChoiceLookupTransformer.accept">Accept</message> - <message key="xmlui.ChoiceLookupTransformer.add">Add</message> - <message key="xmlui.ChoiceLookupTransformer.cancel">Cancel</message> - <message key="xmlui.ChoiceLookupTransformer.more">See More Results</message> - <!-- params are: start, end, total-count, search-value --> - <message key="xmlui.ChoiceLookupTransformer.results">Results @1@ to @2@ of @3@ for "@4@"</message> - <message key="xmlui.ChoiceLookupTransformer.fail">Failed to load choice data: </message> - - <!-- Choice Lookup - sample config for dc.publisher field --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.help">Name of Publisher</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.title">Look up Publisher</message> - <!-- Params are: search-value --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.nonauthority">Non-authority value: @1@</message> - - <!-- Choice Lookup - sample config for dc.contributor.author field --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help">Name in "Last, First" format</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help.last">Last name, e.g. "Smith"</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help.first">First name(s) e.g. "Fred"</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.title">LC Name Authority author lookup</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.nonauthority">Local value "@1@" (not in Naming Authority)</message> - - <!-- mobile theme --> - <message key="xmlui.mobile.home_mobile">Digital Library Mobile</message> - <message key="xmlui.mobile.search_all">Search ALL</message> - <message key="xmlui.mobile.browse_all">Browse ALL by</message> - <message key="xmlui.mobile.browse_date">Date</message> - <message key="xmlui.mobile.browse_author">Author</message> - <message key="xmlui.mobile.browse_title">Title</message> - <message key="xmlui.mobile.browse_subject">Subject</message> - <message key="xmlui.mobile.related_google_scholar">Related</message> - <message key="xmlui.mobile.items_in_google_scholar">Items in Google Scholar</message> - <message key="xmlui.mobile.download">Download</message> - - - <!-- Versioning --> - <message key="xmlui.aspect.versioning.VersioningNavigation.context_create_version">Create version of this item</message> - <message key="xmlui.aspect.versioning.VersioningNavigation.context_show_version_history">Show version history</message> - - <message key="xmlui.aspect.versioning.VersionItemForm.title">Create Version</message> - <message key="xmlui.aspect.versioning.VersionItemForm.trail">Version</message> - <message key="xmlui.aspect.versioning.VersionItemForm.head1">Create new version of item: {0}</message> - <message key="xmlui.aspect.versioning.VersionItemForm.submit_version">Version</message> - <message key="xmlui.aspect.versioning.VersionItemForm.submit_update_version">Update Version</message> - <message key="xmlui.aspect.versioning.VersionItemForm.summary">Reason for creating new version</message> - - <message key="xmlui.aspect.versioning.VersionUpdateForm.title">Update Version</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.trail">Version</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.head1">Update version of item: {0}</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.submit_version">Version</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.submit_update_version">Update Version</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.summary">Summary</message> - - - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.title">Confirm Deletion</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.trail">Confirm deletion</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.head1">Confirm Deletion(s)</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.para1">Are you sure you want to delete these versions. </message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.para2">PLEASE NOTE: That by deleting these versions, the associated items will no longer be accessible.</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column1">Version</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column2">Item</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column3">Editor</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column4">Date</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column5">Summary</message> - - - <message key="xmlui.aspect.versioning.RestoreVersionForm.title">Restore Version</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.trail">Restore Version</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.head1">Restore Version</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.para1">Are you sure you want to restore this version:</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column1">Version</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column2">Editor</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column3">Date</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column4">Summary</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.restore">Restore</message> - - <message key="xmlui.aspect.versioning.VersionHistoryForm.head2">Version History</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column1">Version</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column2">Item</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column3">Editor</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column4">Date</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column5">Summary</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column6">Actions</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.restore">Restore</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.update">Update</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.legend">*Selected version</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.delete">Delete Versions</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.return">Return</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.collection_admins_only">(collection administrators only)</message> - - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.new_version_head">Notice</message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.new_version_help">This is not the latest version of this item. The latest version can be found at: </message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.workflow_version_head">Notice</message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.workflow_version_help">A more recent version of this item is in the Workflow.</message> - - - <message key="xmlui.structure.AboutRepositoryTitle">About This Repository</message> - <message key="xmlui.structure.AboutRepositoryTrail">About This Repository</message> - <message key="xmlui.structure.AboutRepositoryText">To add your own content to this page, edit i18n message files and add your own content to the title, trail, and body.</message> - - - <!-- End Versioning --> - - - <!-- 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> - -</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 deleted file mode 100644 index b8465f27b9ec2c6f0ed31c548b701cbeb50a8916..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/i18n/messages_pt_BR.xml +++ /dev/null @@ -1,2561 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - - 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/ - ---> -<catalogue xml:lang="pt-BR" xmlns:i18n="http://apache.org/cocoon/i18n/2.1"> - - <!-- - The format used by all keys is as follows - - xmlui.<Aspect>.<Java Class>.<name> - - There are a few exceptions to this naming format, - 1) Some general keys are in the xmlui.general namespace - because they are used very frequently. - 2) Some general keys which are specific to a particular aspect - may be found at xmlui.<Aspect> without specifying a - particular java class. - --> - - <!-- TRADUÇÃO IBICT - O formato usado para todas as chave é como se segue - - xmlui.<Aspect>.<Java Class>.<name> - - Existem poucas exceções para este formato de nomeação, - 1) Algumas chaves gerais estão em xmlui.general namespace - porque são usadas muito frequentemente. - 2) Algumas chaves gerais que são especÃficas para um aspecto particular - podem ser encontradas em xmlui. <Aspect> sem especificar uma - classe java particular. - --> - - <!-- General keys --> - <message key="xmlui.general.dspace_home">Página inicial</message> - <message key="xmlui.general.search">Pesquisar</message> - <message key="xmlui.general.go">Ir</message> - <message key="xmlui.general.go_home">Ir para a página inicial</message> - <message key="xmlui.general.save">Salvar</message> - <message key="xmlui.general.cancel">Cancelar</message> - <message key="xmlui.general.return">Voltar</message> - <message key="xmlui.general.update">Alterar</message> - <message key="xmlui.general.delete">Excluir</message> - <message key="xmlui.general.next">Próximo</message> - <message key="xmlui.general.untitled">Sem tÃtulo</message> - <message key="xmlui.general.perform">Executar</message> - <message key="xmlui.general.queue">Fila</message> - - <!-- - Page not found keys - - This is a special component that is not part of any aspect but is added - by manakin to all aspect chains. - --> - <message key="xmlui.PageNotFound.title">Página não encontrada</message> - <message key="xmlui.PageNotFound.head">Página não encontrada</message> - <message key="xmlui.PageNotFound.para1">Não foi possÃvel encontrar a página solicitada</message> - - - <!-- - The "utils" non-aspect - --> - <message key="xmlui.utils.AuthenticationUtil.onlyAdmins">Somente administradorees do site podem assumir login como outro usuário</message> - <message key="xmlui.utils.AuthenticationUtil.onlyAuthenticatedAdmins">Somente usuários autenticados que são administradores podem assumir login como outro usuário</message> - <message key="xmlui.utils.AuthenticationUtil.notAnotherAdmin">Você não possui direitos para logar-se como administrador</message> - - - <!-- - This section is for feed syndications (RSS, atom, etc) - --> - <message key="xmlui.feed.general_description">O Repositório captura, armazena, indexa, preserva e distibui material de pesquisa em formato digital.</message> - <message key="xmlui.feed.header">RSS Feeds</message> - <message key="xmlui.feed.logo_title">O canal de imagem</message> - <message key="xmlui.feed.untitled">Sem TÃtulo</message> - - <!-- - Default notice header - --> - <message key="xmlui.general.notice.default_head">Noticiar</message> - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - ArtifactBrowser Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- org.dspace.app.xmlui.artifactbrowser.AbstractSearch.java --> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_community">Resultados da busca por Comunidade: {0}</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_collection">Resultados da busca por Coleção: {0}</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head1_none">Resultados da busca</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.result_query">Sua consulta "{0}" produziu {1} resultado(s).</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head2">Comunidades ou Coleções correspondentes a sua consulta</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.head3">Resultados para a sua consulta</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.no_results">A busca não retornou resultados.</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.all_of_dspace">Tudo sobre a Biblioteca Digital</message> - - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.title">TÃtulo</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dateissued">data do documento</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.dateaccessioned">data de submissão</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.relevance">Relevância</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by">Ordenar registros por</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order">Ordem</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order.asc">Ascendente</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.order.desc">Descendente</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.rpp">Resultados/páginas</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.AdvancedSearch.java --> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.title">Busca avançada</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.trail">Busca avançada</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.head">Busca avançada</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_scope">Escopo da busca</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_scope_help">Limite a sua busca para uma comunidade ou coleção.</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.conjunction">Conjunção</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_type">Tipo de busca</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.search_for">Buscar por</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_author">Autor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_title">TÃtulo</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_subject">Assunto</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_abstract">Resumo</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_series">Série</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_sponsor">Patrocinador</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_identifier">Identificador</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_language">Idioma/LÃngua (ISO)</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_keyword">Palavra-chave</message> - - <!-- some common other possibilities for Advanced Search Fields --> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_contributor">Contribuidor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_creator">Autor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_subject">Assunto</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_description">Descrição</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_relation">Relação</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_mime">Mime Type</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_other">Outro contribuidor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_advisor">Orientador</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_department">Departamento</message> - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_ANY">Texto completo</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.and">AND (e)</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.or">OR (ou)</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.not">NOT (não)</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.ConfigureableBrowse.java --> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with">Ou digite as primeiras letras:</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.starts_with_help">Navegue pelos itens que começam com essas letras</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_select">Ir para um ponto do Ãndice:</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_month">(Escolha o mês)</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.choose_year">(Escolha o ano)</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year">Ou digite um ano: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.jump_year_help">Navegue pelos itens de um determinado ano.</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.no_results">Desculpe, não há nenhum resultado para essa busca.</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.sort_by"> Classificar por: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.order"> Ordenar: </message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.rpp"> Resultados: </message><!-- /Page --> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.general.etal"> Autores/Item: </message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.etal.all">Todos</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.title">tÃtulo</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.dateissued">data do documento</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.sort_by.dateaccessioned">data de submissão</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.order.asc">Ascendente</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.order.desc">Descendente</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.author.column_heading">Nome dos autores</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.subject.column_heading">Assunto</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.metadata.author">Navegação {0} por autor {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.metadata.author">Navegação {0} por autor</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.metadata.subject">Navegação {0} por assunto {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.metadata.subject">Navegação {0} por assunto</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.title">Navegação {0} por tÃtulo {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.title">Navegação {0} por tÃtulo</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.dateissued">Navegação {0} por data do documento {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.dateissued">Navegação {0} por data do documento</message> - - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.title.item.dateaccessioned">Navegação {0} por data de submissão {1}</message> - <message key="xmlui.ArtifactBrowser.ConfigurableBrowse.trail.item.dateaccessioned">Navegação {0} por data de submissão</message> - - - <!-- org.dspace.app.xmlui.artifactbrowser.CollectionViewer.java --> - <message key="xmlui.ArtifactBrowser.CollectionViewer.search_scope">Escopo da busca</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.all_of_dspace">Todo o repositório</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.full_text_search">Buscar nesta coleção:</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.head_browse">Navegar por</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_titles">TÃtulos</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_authors">Autores</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.browse_dates">Datas</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.advanced_search_link">Pesquisa avançada</message> - <message key="xmlui.ArtifactBrowser.CollectionViewer.head_recent_submissions">Submissões recentes</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.CommunityBrowser.java --> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.title">Lista da comunidade</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.trail">Lista da comunidade</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.head">Comunidades na Biblioteca Digital</message> - <message key="xmlui.ArtifactBrowser.CommunityBrowser.select">Selecione uma comunidade para navegar nas coleções.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.CommunityViewer.java --> - <message key="xmlui.ArtifactBrowser.CommunityViewer.search_scope">Escopo da busca</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.all_of_dspace">Todo o repositório</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.full_text_search">Pesquisar nesta comunidade e nas suas coleções:</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_browse">Navegar por</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_titles">TÃtulos</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_authors">Autores</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.browse_dates">Datas</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.advanced_search_link">Busca avançada</message> - <message key="xmlui.ArtifactBrowser.CommunityViewer.head_sub_communities">Subcomunidades nesta comunidade</message> - <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> - - - <!-- org.dspace.app.xmlui.artifactbrowser.Contact.java --> - <message key="xmlui.ArtifactBrowser.Contact.title">Fale conosco</message> - <message key="xmlui.ArtifactBrowser.Contact.trail">Fale conosco</message> - <message key="xmlui.ArtifactBrowser.Contact.head">Fale conosco</message> - <message key="xmlui.ArtifactBrowser.Contact.para1">{0} Administradores podem ser contatados por:</message> - <message key="xmlui.ArtifactBrowser.Contact.feedback_label">Formulário de contato</message> - <message key="xmlui.ArtifactBrowser.Contact.feedback_link">Fale conosco</message> - <message key="xmlui.ArtifactBrowser.Contact.email">E-mail</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.FeedbackForm.java --> - <message key="xmlui.ArtifactBrowser.FeedbackForm.title">Dê a sua opinião</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.trail">Dê a sua opinião</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.head">Dê a sua opinião</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.para1">Obrigado por compartilhar sua opinião sobre o repositório! Seus comentários são bem-vindos!</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.email">Seu email</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.email_help">Este endereço será utilizado para acompanhamento dos seus comentários.</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.comments">Comentários</message> - <message key="xmlui.ArtifactBrowser.FeedbackForm.submit">Enviar comentários</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.FeedbackSent.java --> - <message key="xmlui.ArtifactBrowser.FeedbackSent.title">Dê a sua opinião</message> - <message key="xmlui.ArtifactBrowser.FeedbackSent.trail">Dê a sua opinião</message> - <message key="xmlui.ArtifactBrowser.FeedbackSent.head">Opinião enviada</message> - <message key="xmlui.ArtifactBrowser.FeedbackSent.para1">Seus comentários foram recebidos.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.FrontPageSearch.java --> - <message key="xmlui.ArtifactBrowser.FrontPageSearch.head">Buscar na Biblioteca Digital</message> - <message key="xmlui.ArtifactBrowser.FrontPageSearch.para1">Digite algum texto na caixa abaixo para buscar na Biblioteca Digital.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.ItemViewer.java --> - <message key="xmlui.ArtifactBrowser.ItemViewer.trail">Ver item</message> - <message key="xmlui.ArtifactBrowser.ItemViewer.head_parent_collections">Este item aparece na(s) seguinte(s) coleção(s)</message> - <message key="xmlui.ArtifactBrowser.ItemViewer.show_simple">Mostrar registro simples</message> - <message key="xmlui.ArtifactBrowser.ItemViewer.show_full">Mostrar registro completo</message> - <message key="xmlui.ArtifactBrowser.ItemViewer.withdrawn">Este item foi removido e não está disponÃvel.</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.Navigation.java --> - <message key="xmlui.ArtifactBrowser.Navigation.head_browse">Navegar</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_all_of_dspace">Todo o repositório</message> - <message key="xmlui.ArtifactBrowser.Navigation.communities_and_collections">Comunidades e Coleções</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_title">TÃtulos</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_author">Autores</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_subject">Assuntos</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_dateissued">Por data do documento</message> - <message key="xmlui.ArtifactBrowser.Navigation.browse_dateaccessioned">Por data de submissão</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_this_collection">Esta coleção</message> - <message key="xmlui.ArtifactBrowser.Navigation.head_this_community">Esta comunidade</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.SimpleSearch.java --> - <message key="xmlui.ArtifactBrowser.SimpleSearch.title">Buscar</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.trail">Buscar</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.head">Buscar</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.search_scope">Escopo da busca</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.full_text_search">Buscar por texto completo</message> - - <!-- org.dspace.app.xmlui.artifactbrowser.RestrictedItem.java --> - <message key="xmlui.ArtifactBrowser.RestrictedItem.title">Este recurso é restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.trail">Restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_resource">Este recurso é restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_community">Esta comunidade é restrita</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_collection">Esta coleção é restrita</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_item">Este item é restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_bitstream">Este bitstream é restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_resource">Você não possui as permissões para acessar este recurso.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_community">Você não possui as permissões para acessar esta comunidade <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_collection">Você não possui as permissões para acessar esta coleção <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item">Você não possui as permissões para acessar este item <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_bitstream">Você não possui as permissões para acessar este bitstream <b>{0}</b>.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_collection">coleção</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_community">communidade</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_bitstream">bitstream</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_item">item</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.type_resource">recurso</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.unknown">desconhecido</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.login">Ir para a tela de login</message> - - <message key="xmlui.ArtifactBrowser.RestrictedItem.head_item_withdrawn">Este item foi removido</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_withdrawn">O item selecionado foi removido e não está mais disponÃvel.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_restricted_auth">O item selecionado é restrito e requer permissão para ser visto. Por favor, faça o login para acessar o item.</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.para_item_restricted">Você não possui direitos de acesso para visualizar este item. Por favor contate o administrador do sistema.</message> - - <!-- Authentication messages used at the top of the login page: --> - <message key="xmlui.ArtifactBrowser.RestrictedItem.auth_header">Este item é restrito</message> - <message key="xmlui.ArtifactBrowser.RestrictedItem.auth_message">O item que você está tentando acessar é de acesso restrito e requer permissão para ser visto. Por favor, faça o login abaixo para acessar o item.</message> - - <message key="xmlui.ArtifactBrowser.StatisticsViewer.choose_month">Relatórios mensais</message> - <message key="xmlui.ArtifactBrowser.StatisticsViewer.report.title">Resumo estatÃstico</message> - - <message key="xmlui.ArtifactBrowser.StatisticsViewer.no_report.title">Nenhum relatório disponÃvel atualmente</message> - <message key="xmlui.ArtifactBrowser.StatisticsViewer.no_report.text">Atualmente não há relatórios disponÃveis para este serviço. Por favor, tente mais tarde</message> - - <!-- Authentication messages used for bitstream authentication --> - <message key="xmlui.BitstreamReader.auth_header">O arquivo é restrito</message> - <message key="xmlui.BitstreamReader.auth_message">O arquivo que você está tentando acessar é de acesso restrito e requer permissão para ser visto. Por favor, faça o login abaixo para acessar o arquivo.</message> - - <!-- Export Archive download messages --> - <message key="xmlui.ItemExportDownloadReader.auth_header">Este arquivo exportado é restrito.</message> - <message key="xmlui.ItemExportDownloadReader.auth_message">O arquivo exportado que você está tentando acessar é de acesso restrito e requer permissão para ser visto. Por favor, faça o login abaixo para acessar o arquivo exportado. </message> - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - EPerson Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- General keys used by the EPerson aspect --> - <message key="xmlui.EPerson.trail_new_registration">Cadastro de usuário</message> - <message key="xmlui.EPerson.trail_forgot_password">Esqueceu sua senha?</message> - - <!-- org.dspace.app.xmlui.eperson.CannotRegister.java --> - <message key="xmlui.EPerson.CannotRegister.title">Cadastro indisponÃvel</message> - <message key="xmlui.EPerson.CannotRegister.head">Cadastro indisponÃvel</message> - <message key="xmlui.EPerson.CannotRegister.para1">A configuração deste repositório não permite o registo neste contexto. Por favor, entre em contato com o <a href="../contact">administrador do site</a> para questões e comentários.</message> - - <!-- org.dspace.app.xmlui.eperson.EditProfile.java --> - <message key="xmlui.EPerson.EditProfile.title_update">Atualizar perfil</message> - <message key="xmlui.EPerson.EditProfile.title_create">Criar perfil</message> - <message key="xmlui.EPerson.EditProfile.trail_update">Criar perfil</message> - <message key="xmlui.EPerson.EditProfile.head_update">Criar perfil</message> - <message key="xmlui.EPerson.EditProfile.head_create">Criar perfil</message> - <message key="xmlui.EPerson.EditProfile.email_address">Endereço de e-mail</message> - <message key="xmlui.EPerson.EditProfile.first_name">Nome</message> - <message key="xmlui.EPerson.EditProfile.last_name">Sobrenome</message> - <message key="xmlui.EPerson.EditProfile.telephone">Telefone</message> - <message key="xmlui.EPerson.EditProfile.Language">Idioma</message> - <message key="xmlui.EPerson.EditProfile.subscriptions">Assinaturas</message> - <message key="xmlui.EPerson.EditProfile.subscriptions_help">Você pode assinar coleções para receber alerta de e-mails diários sobre os novos itens adicionados. Você pode assinar quantas coleções desejar. Outra alternativa para receber alerta de e-mails diários é usar os RSS feeds disponÃveis para todas as coleções.</message> - <message key="xmlui.EPerson.EditProfile.email_subscriptions">Assinaturas de e-mail</message> - <message key="xmlui.EPerson.EditProfile.select_collection">( Selecione a coleção )</message> - <message key="xmlui.EPerson.EditProfile.update_password_instructions">Opcionalmente, você pode digitar uma nova senha na caixa abaixo e confirme digitando-a novamente na segunda caixa. A senha deve conter, no mÃnimo, seis caracteres.</message> - <message key="xmlui.EPerson.EditProfile.create_password_instructions">Por favor, digite uma senha na caixa abaixo, e confirme digitando-a novamente na segunda caixa. A senha deve conter, no mÃnimo, seis caracteres.</message> - <message key="xmlui.EPerson.EditProfile.password">Senha</message> - <message key="xmlui.EPerson.EditProfile.confirm_password">Redigite a senha</message> - <message key="xmlui.EPerson.EditProfile.submit_update">Cadastro completo</message> - <message key="xmlui.EPerson.EditProfile.submit_create">Atualizar perfil</message> - <message key="xmlui.EPerson.EditProfile.error_required">Campo é obrigatório</message> - <message key="xmlui.EPerson.EditProfile.error_invalid_password">Escolha uma senha com pelo menos 6 caracteres</message> - <message key="xmlui.EPerson.EditProfile.error_unconfirmed_password">Por favor confirme a senha digitada</message> - <message key="xmlui.EPerson.EditProfile.head_auth">Grupos autorizados a que pertence</message> - <message key="xmlui.EPerson.EditProfile.head_identify">Identificar</message> - <message key="xmlui.EPerson.EditProfile.head_security">Segurança</message> - - <!-- org.dspace.app.xmlui.eperson.EPersonUtils.java --> - <message key="xmlui.EPerson.EPersonUtils.register_verify_email">Verificar e-mail</message> - <message key="xmlui.EPerson.EPersonUtils.register_create_profile">Criar perfil</message> - <message key="xmlui.EPerson.EPersonUtils.register_finished">ConcluÃdo</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_verify_email">Verificar e-mail</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_reset_password">Alterar senha</message> - <message key="xmlui.EPerson.EPersonUtils.forgot_finished">ConcluÃdo</message> - - <!-- org.dspace.app.xmlui.eperson.ForgotPasswordFinished.java --> - <message key="xmlui.EPerson.ForgotPasswordFinished.title">Alterar senha</message> - <message key="xmlui.EPerson.ForgotPasswordFinished.head">Alterar senha</message> - <message key="xmlui.EPerson.ForgotPasswordFinished.para1">Sua senha foi alterada.</message> - - <!-- org.dspace.app.xmlui.eperson.InvalidToken.java --> - <message key="xmlui.EPerson.InvalidToken.title">Token inválido</message> - <message key="xmlui.EPerson.InvalidToken.trail">Token inválido</message> - <message key="xmlui.EPerson.InvalidToken.head">Token inválido</message> - <message key="xmlui.EPerson.InvalidToken.para1">A URL fornecida é inválida. A URL pode ter sido quebrada em várias linhas no seu cliente de e-mail, como esta:</message> - <message key="xmlui.EPerson.InvalidToken.para2">Se assim for, copie e cole a URL diretamente na barra de naveação ao invés de simplesmente clicar no link. O endereço na barra de navegação deverá ser algo como:</message> - - <!-- org.dspace.app.xmlui.eperson.Navigation.java --> - <message key="xmlui.EPerson.Navigation.my_account">Minha conta</message> - <message key="xmlui.EPerson.Navigation.profile">Perfil</message> - <message key="xmlui.EPerson.Navigation.logout">Sair</message> - <message key="xmlui.EPerson.Navigation.login">Entrar</message> - <message key="xmlui.EPerson.Navigation.register">Cadastro</message> - - <!-- org.dspace.app.xmlui.eperson.PasswordLogin.java --> - <message key="xmlui.EPerson.PasswordLogin.title">Entrar</message> - <message key="xmlui.EPerson.PasswordLogin.trail">Entrar</message> - <message key="xmlui.EPerson.PasswordLogin.head1">Entrar na Biblioteca Digital</message> - <message key="xmlui.EPerson.PasswordLogin.title">Entrar</message> - <message key="xmlui.EPerson.PasswordLogin.email_address">Endereço de e-mail</message> - <message key="xmlui.EPerson.PasswordLogin.error_bad_login">O e-mail e/ou senha são inválidos.</message> - <message key="xmlui.EPerson.PasswordLogin.password">Senha</message> - <message key="xmlui.EPerson.PasswordLogin.forgot_link"> Esqueceu a senha?</message> - <message key="xmlui.EPerson.PasswordLogin.submit">Entrar</message> - <message key="xmlui.EPerson.PasswordLogin.head2">Cadastrar novo usuário</message> - <message key="xmlui.EPerson.PasswordLogin.para1">Cadastre uma conta para se inscrever nas coleções e receber atualizações por e-mail e enviar novos itens para a Biblioteca Digital.</message> - <message key="xmlui.EPerson.PasswordLogin.register_link">Clique aqui para cadastrar.</message> - - <!-- org.dspace.app.xmlui.eperson.LDAPLogin.java --> - <message key="xmlui.EPerson.LDAPLogin.title">Entrar</message> - <message key="xmlui.EPerson.LDAPLogin.trail">Entrar</message> - <message key="xmlui.EPerson.LDAPLogin.head1">Entrar na Biblioteca Digital</message> - <message key="xmlui.EPerson.LDAPLogin.title">Entrar</message> - <message key="xmlui.EPerson.LDAPLogin.username">Nome de usuário</message> - <message key="xmlui.EPerson.LDAPLogin.error_bad_login">O nome de usuário e/ou senha não são válidos.</message> - <message key="xmlui.EPerson.LDAPLogin.password">Senha</message> - <message key="xmlui.EPerson.LDAPLogin.submit">Entrar</message> - - <!-- org.dspace.app.xmlui.eperson.LoginChooser.java --> - <message key="xmlui.EPerson.LoginChooser.title">Escolha um modo de login</message> - <message key="xmlui.EPerson.LoginChooser.trail">Escolha um login</message> - <message key="xmlui.EPerson.LoginChooser.head1">Escolha um modo de login</message> - <message key="xmlui.EPerson.LoginChooser.para1">Entrar via:</message> - <message key="org.dspace.authenticate.ShibAuthentication.title">autenticação Shibboleth</message> - <message key="org.dspace.eperson.LDAPAuthentication.title">autenticação LDAP</message> - <message key="org.dspace.eperson.PasswordAuthentication.title">autenticação de senha</message> - <message key="org.dspace.eperson.X509Authentication.title">autenticação de certificado da web</message> - - <!-- org.dspace.app.xmlui.eperson.FailedAuthentication --> - <message key="xmlui.EPerson.FailedAuthentication.BadCreds">As permissões fornecidas são inválidas.</message> - <message key="xmlui.EPerson.FailedAuthentication.BadArgs">Não é possÃvel autenticar. Argumentos inválidos.</message> - <message key="xmlui.EPerson.FailedAuthentication.NoSuchUser">Usuário não encontrado.</message> - <message key="xmlui.EPerson.FailedAuthentication.title">Falha na autenticação</message> - <message key="xmlui.EPerson.FailedAuthentication.trail">Falha na autenticação</message> - <message key="xmlui.EPerson.FailedAuthentication.h1">Falha na autenticação</message> - - <!-- Login xml files --> - <message key="xmlui.eperson.noAuthMethod.head">Nenhum modo de autenticação encontrado</message> - <message key="xmlui.eperson.noAuthMethod.p1">Nenhum modo de autenticação foi encontrado. Por favor, entre em contato com o administrador do site.</message> - <message key="xmlui.eperson.shibbLoginFailure.head">Shibboleth Falha no login</message> - <message key="xmlui.eperson.shibbLoginFailure.p1">Shibboleth autenticação não disponÃvel no momento. Por favor, entre em contato com o administrador do site.</message> - - <!-- org.dspace.app.xmlui.eperson.ProfileUpdated.java --> - <message key="xmlui.EPerson.ProfileUpdated.title">Atualizar perfil</message> - <message key="xmlui.EPerson.ProfileUpdated.trail">Atualizar perfil</message> - <message key="xmlui.EPerson.ProfileUpdated.head">Atualizar perfil</message> - <message key="xmlui.EPerson.ProfileUpdated.para1">As informações do seu perfil foram atualizadas.</message> - - <!-- org.dspace.app.xmlui.eperson.RegistrationFinished.java --> - <message key="xmlui.EPerson.RegistrationFinished.title">Cadastro finalizado</message> - <message key="xmlui.EPerson.RegistrationFinished.head">Cadastro finalizado</message> - <message key="xmlui.EPerson.RegistrationFinished.para1">Você está agora cadastrado para usar a Biblioteca Digital. Você pode se inscrever nas coleções para receber e-mails sobre novos itens cadastrados.</message> - - <!-- org.dspace.app.xmlui.eperson.ResetPassword.java --> - <message key="xmlui.EPerson.ResetPassword.title">Alterar senha</message> - <message key="xmlui.EPerson.ResetPassword.head">Alterar senha</message> - <message key="xmlui.EPerson.ResetPassword.para1">Por favor, digite uma senha na caixa abaixo e confirme digitando-a novamente na segunda caixa. A senha deve conter, no mÃnimo, seis caracteres.</message> - <message key="xmlui.EPerson.ResetPassword.email_address">Endereço de e-mail</message> - <message key="xmlui.EPerson.ResetPassword.new_password">Nova senha</message> - <message key="xmlui.EPerson.ResetPassword.confirm_password">Digite novamente para confirmar</message> - <message key="xmlui.EPerson.ResetPassword.submit">Alterar senha</message> - <message key="xmlui.EPerson.ResetPassword.error_invalid_password">Escolha uma senha com pelo menos 6 caracteres</message> - <message key="xmlui.EPerson.ResetPassword.error_unconfirmed_password">Por favor, digite novamente a sua senha para confirmar</message> - - <!-- org.dspace.app.xmlui.eperson.StartForgotPassword.java --> - <message key="xmlui.EPerson.StartForgotPassword.title">Esqueceu a senha?</message> - <message key="xmlui.EPerson.StartForgotPassword.head">Esqueceu a senha?</message> - <message key="xmlui.EPerson.StartForgotPassword.para1">Digite o endereço de e-mail que você utilizou para se cadastrar na Biblioteca Digital. Um e-mail será enviado ao endereço com instruções.</message> - <message key="xmlui.EPerson.StartForgotPassword.email_address">Endereço de e-mail</message> - <message key="xmlui.EPerson.StartForgotPassword.email_address_help">Digite o mesmo endereço de e-mail utilizado durante o cadastro.</message> - <message key="xmlui.EPerson.StartForgotPassword.error_not_found">Endereço de e-mail não encontrado.</message> - <message key="xmlui.EPerson.StartForgotPassword.submit">Enviar</message> - - <!-- org.dspace.app.xmlui.eperson.StartRegistration.java --> - <message key="xmlui.EPerson.StartRegistration.title">Cadastro de novo usuário</message> - <message key="xmlui.EPerson.StartRegistration.head1">E-mail já utilizado</message> - <message key="xmlui.EPerson.StartRegistration.para1">Este endereço de e-mail já está sendo utilizado em outra conta. Se você desejar redefinir a senha para esta conta, clique em Alterar senha no botão abaixo.</message> - <message key="xmlui.EPerson.StartRegistration.reset_password_for">Alterar senha para</message> - <message key="xmlui.EPerson.StartRegistration.submit_reset">Alterar senha</message> - <message key="xmlui.EPerson.StartRegistration.head2">Cadastro de novo usuário</message> - <message key="xmlui.EPerson.StartRegistration.para2">Cadastre uma conta para para se inscrever nas coleções e receber atualizações por e-mail e enviar novos itens para a Biblioteca Digital.</message> - <message key="xmlui.EPerson.StartRegistration.email_address">Endereço de e-mail</message> - <message key="xmlui.EPerson.StartRegistration.email_address_help">Este endereço será verificado e usado como seu nome de login.</message> - <message key="xmlui.EPerson.StartRegistration.error_bad_email">Não é possÃvel enviar e-mail para este endereço.</message> - <message key="xmlui.EPerson.StartRegistration.submit_register">Cadastro</message> - - <!-- org.dspace.app.xmlui.eperson.VerifyEmail.java --> - <message key="xmlui.EPerson.VerifyEmail.title">E-mail de confirmação enviado</message> - <message key="xmlui.EPerson.VerifyEmail.head">E-mail de confirmação enviado</message> - <message key="xmlui.EPerson.VerifyEmail.para">Um e-mail foi enviado para {0} contendo uma URL especial e outras informações.</message> - - - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Submission Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - - - <!-- general submission aspect messages --> - <message key="xmlui.Submission.general.mydspace_home">Página inicial</message> - <message key="xmlui.Submission.general.go_mydspace">Ir para página principal</message> - <message key="xmlui.Submission.general.submission.title">Item submetido</message> - <message key="xmlui.Submission.general.submission.trail">Item submetido</message> - <message key="xmlui.Submission.general.submission.head">Item submetido</message> - <message key="xmlui.Submission.general.submission.previous">Anterior</message> - <message key="xmlui.Submission.general.submission.save">Salvar e Sair</message> - <message key="xmlui.Submission.general.submission.next">Próximo</message> - <message key="xmlui.Submission.general.submission.complete">Submissão completa</message> - <message key="xmlui.Submission.general.workflow.title">Item submetido</message> - <message key="xmlui.Submission.general.workflow.trail">Item submetido</message> - <message key="xmlui.Submission.general.workflow.head">Item submetido</message> - <message key="xmlui.Submission.general.showfull">Mostrar registro completo</message> - <message key="xmlui.Submission.general.showsimple">Mostrar registro simples</message> - <message key="xmlui.Submission.general.default.title">Submissão</message> - <message key="xmlui.Submission.general.default.trail">Submissão</message> - - <!-- org.dspace.app.xmlui.submission.CollectiovViewer --> - <message key="xmlui.Submission.CollectionViewer.link1">Submeter um novo item à coleção</message> - - <!-- org.dspace.app.xmlui.submission.Navigation --> - <message key="xmlui.Submission.Navigation.submissions">Submissões</message> - - <!-- org.dspace.app.xmlui.Submission.submissions --> - <message key="xmlui.Submission.Submissions.title">Submissões e Fluxo de submissões</message> - <message key="xmlui.Submission.Submissions.trail">Submissões</message> - <message key="xmlui.Submission.Submissions.head">Submissões e Tarefas do fluxo de submissões</message> - <message key="xmlui.Submission.Submissions.untitled"><i>Sem tÃtulo</i></message> - <message key="xmlui.Submission.Submissions.email">e-mail: </message> - - <!-- Same transformer, workflow section --> - <message key="xmlui.Submission.Submissions.workflow_head1">Tarefas do fluxo de submissões</message> - <message key="xmlui.Submission.Submissions.workflow_info1">Estas tarefas são itens que estão aguardando aprovação antes de serem adicionados ao repositório. Existem duas listas de tarefas, uma com as tarefas que você escolheu para fazer e outra para as tarefas que ainda ninguém está trabalhando.</message> - <message key="xmlui.Submission.Submissions.workflow_head2">Tarefas que você possui</message> - <message key="xmlui.Submission.Submissions.workflow_column1"></message> - <message key="xmlui.Submission.Submissions.workflow_column2">Tarefa</message> - <message key="xmlui.Submission.Submissions.workflow_column3">Item</message> - <message key="xmlui.Submission.Submissions.workflow_column4">Coleção</message> - <message key="xmlui.Submission.Submissions.workflow_column5">Submetedor</message> - <message key="xmlui.Submission.Submissions.workflow_submit_return">Voltar tarefas selecionadas para o conjunto</message> - <message key="xmlui.Submission.Submissions.workflow_info2">Não há tarefas atribuÃdas a você</message> - <message key="xmlui.Submission.Submissions.workflow_head3">Tarefas no conjunto</message> - <message key="xmlui.Submission.Submissions.workflow_submit_take">Fazer tarefas selecionadas</message> - <message key="xmlui.Submission.Submissions.workflow_info3">Sem tarefas no conjunto</message> - <!-- Same transformer, submissions section --> - <message key="xmlui.Submission.Submissions.submit_head1">Submissões</message> - <message key="xmlui.Submission.Submissions.submit_info1a">Você pode </message> - <message key="xmlui.Submission.Submissions.submit_info1b">Iniciar nova submissão</message> - <message key="xmlui.Submission.Submissions.submit_info1c">O processo de submissão inclui a descrição de um item e realizar o upload do(s) arquivo(s) que o compõe. Cada comunidade ou coleção pode definir a sua própria polÃtica para submissão.</message> - <message key="xmlui.Submission.Submissions.submit_head2">Submissões incompletas</message> - <message key="xmlui.Submission.Submissions.submit_info2a">Estes são itens submetidos incompletos. Você também pode </message> - <message key="xmlui.Submission.Submissions.submit_info2b">iniciar outra submissão</message> - <message key="xmlui.Submission.Submissions.submit_info2c">.</message> - <message key="xmlui.Submission.Submissions.submit_column1"></message> - <message key="xmlui.Submission.Submissions.submit_column2">TÃtulo</message> - <message key="xmlui.Submission.Submissions.submit_column3">Coleção</message> - <message key="xmlui.Submission.Submissions.submit_column4">Submetedor</message> - <message key="xmlui.Submission.Submissions.submit_head3">Criação:</message> - <message key="xmlui.Submission.Submissions.submit_info3">Nenhuma submissão incompleta.</message> - <message key="xmlui.Submission.Submissions.submit_head4">Supervisão:</message> - <message key="xmlui.Submission.Submissions.submit_submit_remove">Excluir submissões selecionadas</message> - <!-- Same transformer, inprogress section --> - <message key="xmlui.Submission.Submissions.progress_head1">Submissões para serem revisadas</message> - <message key="xmlui.Submission.Submissions.progress_info1">Estas são as suas submissões concluÃdas que estão sendo analisadas pelos revisores da coleção.</message> - <message key="xmlui.Submission.Submissions.progress_column1">TÃtulo</message> - <message key="xmlui.Submission.Submissions.progress_column2">Coleção</message> - <message key="xmlui.Submission.Submissions.progress_column3">Status</message> - <!-- Same transformer, workflow status --> - <message key="xmlui.Submission.Submissions.status_0">Submetedor</message> - <message key="xmlui.Submission.Submissions.status_1">Aguardando revisão</message> - <message key="xmlui.Submission.Submissions.status_2">Submissão sendo revisada</message> - <message key="xmlui.Submission.Submissions.status_3">Aguardando edição</message> - <message key="xmlui.Submission.Submissions.status_4">Submissão sendo editada</message> - <message key="xmlui.Submission.Submissions.status_5">Aguardando edição final</message> - <message key="xmlui.Submission.Submissions.status_6">Submissão sendo editada</message> - <message key="xmlui.Submission.Submissions.status_7">Submissão foi arquivada</message> - <message key="xmlui.Submission.Submissions.status_unknown">Status desconhecido</message> - <!-- Same transformer, completed submissions section --> - <message key="xmlui.Submission.Submissions.completed.head">Submissões arquivadas</message> - <message key="xmlui.Submission.Submissions.completed.info">Estas são as submissões completas que foram aceitas para a Biblioteca Digital.</message> - <message key="xmlui.Submission.Submissions.completed.column1">Data de aceitação</message> - <message key="xmlui.Submission.Submissions.completed.column2">TÃtulo</message> - <message key="xmlui.Submission.Submissions.completed.column3">Coleção</message> - <message key="xmlui.Submission.Submissions.completed.limit">Nós temos listadas acima apenas 50 das suas submissões arquivadas. </message> - <message key="xmlui.Submission.Submissions.completed.displayall">Exibir todas as minhas submissões arquivadas.</message> - - <!-- submission progress bar messages --> - <message key="xmlui.Submission.submit.progressbar.initial-questions">Questões iniciais</message> - <message key="xmlui.Submission.submit.progressbar.describe">Descrever</message> - <message key="xmlui.Submission.submit.progressbar.access">Acessar</message> - <message key="xmlui.Submission.submit.progressbar.upload">Upload</message> - <message key="xmlui.Submission.submit.progressbar.verify">Revisão</message> - <message key="xmlui.Submission.submit.progressbar.creative-commons">Creative Commons</message> - <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> - - <!-- org.dspace.app.xmlui.Submission.submit.ResumeStep --> - <message key="xmlui.Submission.submit.ResumeStep.submit_resume">Resumo</message> - - <!-- org.dspace.app.xmlui.Submission.submit.SelectCollection --> - <message key="xmlui.Submission.submit.SelectCollection.head">Escolha uma coleção</message> - <message key="xmlui.Submission.submit.SelectCollection.collection">Coleção</message> - <message key="xmlui.Submission.submit.SelectCollection.collection_help">Escolha a coleção que você deseja enviar um item.</message> - <message key="xmlui.Submission.submit.SelectCollection.collection_default">Escolha uma coleção...</message> - - <!-- org.dspace.app.xmlui.Submission.submit.SaveOrRemoveStep --> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.head">Salvar ou cancelar sua submissão?</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.info1">Você quer Excluir a submissão ou deseja continuar a trabalhar com o item depois? Você pode retornar ao processo de submissão se clicar em Sair acidentalmente.</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_back">Ops, continuar submissão</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_save">Salvar, vou trabalhar com isso mais tarde</message> - <message key="xmlui.Submission.submit.SaveOrRemoveStep.submit_remove">Excluir a submissão</message> - - - <!-- org.dpspace.app.xmlui.Submission.submit.InitialQuestionsStep --> - <message key="xmlui.Submission.submit.InitialQuestionsStep.head">Questões iniciais</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.important_note">Nota importante: </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.and"> e </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.separator">, </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.open_set"> (</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.close_set">)</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles">Vários tÃtulos</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles_help">O item tem mais de um tÃtulo, <i>isto é, um item traduzido</i></message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.multiple_titles_note">Se a caixa acima for inválida, em seguida, o seguinte tÃtulo será removido do item: </message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before">Publicado</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before_help">O item foi publicado ou distribuÃdo publicamente antes</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.published_before_note">Se a caixa acima for inválida em seguida será removido do item:</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.date_issued">Data do documento</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.citation">Citação</message> - <message key="xmlui.Submission.submit.InitialQuestionsStep.publisher">Editor</message> - - <!-- org.dspace.app.xmlui.Submission.submit.DescribeStep --> - <message key="xmlui.Submission.submit.DescribeStep.head">Descrever o item</message> - <message key="xmlui.Submission.submit.DescribeStep.unknown_field">Erro: tipo de campo desconhecido</message> - <message key="xmlui.Submission.submit.DescribeStep.required_field">Este campo é necessário</message> - <message key="xmlui.Submission.submit.DescribeStep.last_name_help">último nome, <i>por exemplo, Silva</i></message> - <message key="xmlui.Submission.submit.DescribeStep.first_name_help">Primeiro nome(s) + "Jr", <i>por exemplo, João</i></message> - <message key="xmlui.Submission.submit.DescribeStep.year">Ano</message> - <message key="xmlui.Submission.submit.DescribeStep.month">Mês</message> - <message key="xmlui.Submission.submit.DescribeStep.day">Dia</message> - <message key="xmlui.Submission.submit.DescribeStep.series_name">Nome da série</message> - <message key="xmlui.Submission.submit.DescribeStep.report_no">Relatório ou número do trabalho.</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.link">Categorias de assunto</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.title">Categorias de assunto</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.filter.label">Filtro de assuntos</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.filter.button">Filtro</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.loading">Por favor, espere enquanto o vocabulário controlado é carregado.</message> - <message key="xmlui.Submission.submit.DescribeStep.controlledvocabulary.error">Ocorreu um problema na carga do vocabulário controlado, por favor, tente mais tarde.</message> - - - <!-- org.dspace.app.xmlui.Submission.submit.AccessStep --> - <message key="xmlui.Submission.submit.AccessStep.head">Configurações sobre o acesso</message> - <message key="xmlui.Submission.submit.AccessStep.access_settings">VisÃvel a um grupo selecionado de usuários (não acessÃvel aos usuário anonimos)</message> - <message key="xmlui.Submission.submit.AccessStep.open_access">O item estará visÃvel ao final do processo, aceito e arquivado</message> - <message key="xmlui.Submission.submit.AccessStep.embargo">Acesso embargado até uma data especÃfica</message> - <message key="xmlui.Submission.submit.AccessStep.embargo_visible">VisÃvel/Embargado</message> - <message key="xmlui.Submission.submit.AccessStep.name">Nome</message> - <message key="xmlui.Submission.submit.AccessStep.description">Descriçãon</message> - <message key="xmlui.Submission.submit.AccessStep.reason">Razão</message> - <message key="xmlui.Submission.submit.AccessStep.submit_add_policy">Confirmar polÃtica & adicionar outra</message> - <message key="xmlui.Submission.submit.AccessStep.list_assigned_groups">Grupos</message> - <message key="xmlui.Submission.submit.AccessStep.error_format_date">Erro no formato da data</message> - <message key="xmlui.Submission.submit.AccessStep.error_missing_date">Quando a opção de embargo é selecionada, a data torna-se obrigatória</message> - <message key="xmlui.Submission.submit.AccessStep.error_duplicated_policy">Uma polÃtica identica ao grupo e essa ação está vigente.</message> - <message key="xmlui.Submission.submit.AccessStep.table_policies">Lista de polÃticas</message> - <message key="xmlui.Submission.submit.AccessStep.private_settings">Itens restritos</message> - <message key="xmlui.Submission.submit.AccessStep.private_settings_help">Se selecionado, as informações do item não serão indexados para busca</message> - <message key="xmlui.Submission.submit.AccessStep.column0">Nome</message> - <message key="xmlui.Submission.submit.AccessStep.column1">Ação</message> - <message key="xmlui.Submission.submit.AccessStep.column2">Grupo</message> - <message key="xmlui.Submission.submit.AccessStep.column3">Data inicial</message> - <message key="xmlui.Submission.submit.AccessStep.column4">Data Final</message> - <message key="xmlui.Submission.submit.AccessStep.table_edit_button">Editar</message> - <message key="xmlui.Submission.submit.AccessStep.table_delete_button">Remover</message> - <message key="xmlui.administrative.authorization.AccessStep.label_date_help">Formatos de data aceitável: yyyy (ano), yyyy-mm (ano e mês), yyyy-mm-dd (ano, mês e dia)</message> - - - <!-- org.dspace.app.xmlui.Submission.submit.EditPolicyStep --> - <message key="xmlui.Submission.submit.EditPolicyStep.head">Editar polÃtica</message> - - <!-- org.dspace.app.xmlui.Submission.submit.UploadStep --> - <message key="xmlui.Submission.submit.UploadStep.head">Upload do arquivo(s)</message> - <message key="xmlui.Submission.submit.UploadStep.file">Arquivo</message> - <message key="xmlui.Submission.submit.UploadStep.file_help">Por favor, indique o caminho completo do arquivo em seu computador correspondente ao item. Se você clicar em "Buscar...", uma nova janela irá abrir permitindo que você selecione o arquivo em seu computador.</message> - <message key="xmlui.Submission.submit.UploadStep.file_error">O item deve conter pelo menos um arquivo.</message> - <message key="xmlui.Submission.submit.UploadStep.upload_error">Houve uma falha ao carregar o arquivo. Ou o nome digitado está incorreto, houve um problema na rede que impediu o carregamento do arquivo corretamente ou você tentou carregar um arquivo marcado somente para uso interno do sistema. Por favor, tente novamente. </message> - <message key="xmlui.Submission.submit.UploadStep.virus_error">O arquivo não foi carregado, pois parece conter um vÃrus. Entre em contato com o administrador do sistema.</message> - <message key="xmlui.Submission.submit.UploadStep.virus_checker_error">Um problema técnico foi encontrado enquanto tentava verificar a existência de vÃrus no arquivo. Por favor, entre em contato com o administrador do sistema.</message> - <message key="xmlui.Submission.submit.UploadStep.description">Descrição do arquivo</message> - <message key="xmlui.Submission.submit.UploadStep.description_help">Opcionalmente, poderá fornecer uma breve descrição do arquivo, por exemplo "<i>Artigo principal</i>", ou "<i>Leitura de dados da experiência</i>".</message> - <message key="xmlui.Submission.submit.UploadStep.submit_upload">Upload do arquivo e Adicionar outro</message> - <message key="xmlui.Submission.submit.UploadStep.head2">Arquivos enviados</message> - <message key="xmlui.Submission.submit.UploadStep.column0">Primário</message> - <message key="xmlui.Submission.submit.UploadStep.column1"> </message> - <message key="xmlui.Submission.submit.UploadStep.column2">Arquivo</message> - <message key="xmlui.Submission.submit.UploadStep.column3">Tamanho</message> - <message key="xmlui.Submission.submit.UploadStep.column4">Descrição</message> - <message key="xmlui.Submission.submit.UploadStep.column5">Formato</message> - <message key="xmlui.Submission.submit.UploadStep.column6"></message> - <message key="xmlui.Submission.submit.UploadStep.unknown_name">Desconhecido</message> - <message key="xmlui.Submission.submit.UploadStep.unknown_format">Formato desconhecido</message> - <message key="xmlui.Submission.submit.UploadStep.supported">(Válido)</message> - <message key="xmlui.Submission.submit.UploadStep.known">(Conhecido)</message> - <message key="xmlui.Submission.submit.UploadStep.unsupported">(Inválido)</message> - <message key="xmlui.Submission.submit.UploadStep.submit_edit">Editar</message> - <message key="xmlui.Submission.submit.UploadStep.checksum">Verificação do arquivo:</message> - <message key="xmlui.Submission.submit.UploadStep.submit_remove">Excluir arquivos selecionados</message> - - - - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.head">Carregar arquivo(s)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file">Arquivo</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file_help">Por favor, entre com a localização completa do arquivo no seu computador. Caso clique em "navegar...", uma nova janela se abrirá para permitir que navegue e selecione o arquivo no seu computador.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.file_error">A submissão deve conter, no mÃnimo, um arquivo.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.upload_error">Ocorreu um problema na carga do arquivo. O nome do arquivo está incorreto, ou houve um problema de rede, que impediu o acesso ao arquivo de forma correta. Pode ter tentado carregar um arquivo de uso interno e exlcusivo do computador. Por favor, tente novamente.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.virus_error">O arquivo não foi carregado e, aparentemente, contem vÃrus. Por favor, contate o administrado do sistema.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.virus_checker_error">Um problema técnico foi encontrado enquanto tentava verificar se o arquivo contem vÃrus. Por favor, contate o administrado do sistema.</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.description">Descrição do arquivo</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.description_help">Opcionalmente, forneça uma breve descrição do arquivo, pro exemplo "<i>Artigo principal</i>", ou "<i>Relatório de pesquisa</i>".</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_upload">Carregar arquivo & adicionar outro</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.head2">Arquivo carregado</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column0">Primário</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column1"> </message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column2">Arquivo</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column3">Tamanho</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column4">Descrição</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column5">Formato</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.column6"></message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unknown_name">Desconhecido</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unknown_format">Formato desconhecido</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.supported">(Suportado)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.known">(Conhecido)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.unsupported">(Não suportado)</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_edit">Editar</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.checksum">Checksum(soma de verificação) do arquivo:</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_remove">Remover arquivos selecionados</message> - <message key="xmlui.Submission.submit.UploadWithEmbargoStep.submit_policy">PolÃticas</message> - - - <!-- org.dspace.app.xmlui.Submission.submit.EditFileStep --> - <message key="xmlui.Submission.submit.EditFileStep.head">Editar arquivo</message> - <message key="xmlui.Submission.submit.EditFileStep.file">Arquivo</message> - <message key="xmlui.Submission.submit.EditFileStep.description">Descrição do arquivo</message> - <message key="xmlui.Submission.submit.EditFileStep.description_help">Opcionalmente, poderá fornecer uma breve descrição do arquivo, por exemplo "<i>Artigo principal</i>", ou "<i>Leitura de dados da experiência</i>".</message> - <message key="xmlui.Submission.submit.EditFileStep.info1">Selecione o formato do arquivo a partir da lista abaixo, por exemplo, "<i>Adobe PDF</i>" ou "<i>Microsoft Word</i>." <strong>Se o formato não está na lista </strong>, por favor descreva-o na caixa de entrada abaixo da lista.</message> - <message key="xmlui.Submission.submit.EditFileStep.format_detected">Formato identificado</message> - <message key="xmlui.Submission.submit.EditFileStep.format_selected">Selecionar formato</message> - <message key="xmlui.Submission.submit.EditFileStep.format_default">Formato não consta na lista</message> - <message key="xmlui.Submission.submit.EditFileStep.info2">Se o formato não está na lista acima, <strong>selecione "Formato não consta na lista" acima</strong> e descreva o formato do arquivo na caixa abaixo.</message> - <message key="xmlui.Submission.submit.EditFileStep.format_user">Outro formato</message> - <message key="xmlui.Submission.submit.EditFileStep.format_user_help">O número do aplicativo que você usou para criar o arquivo e o número da versão (por exemplo, "<i>ACMESoft SuperApp version 1.5</i>").</message> - - <!-- org.dspace.app.xmlui.Submission.submit.EditBitstreamPolicies --> - <message key="xmlui.Submission.submit.EditBitstreamPolicies.head">Editar acesso dos arquivos binários</message> - - - <!-- org.dspace.app.xmlui.Submission.submit.ReviewStep --> - <message key="xmlui.Submission.submit.ReviewStep.head">Revisar a submissão </message> - <message key="xmlui.Submission.submit.ReviewStep.yes">Sim</message> - <message key="xmlui.Submission.submit.ReviewStep.no">Não</message> - <message key="xmlui.Submission.submit.ReviewStep.submit_jump">Corrigir um destes</message> - <message key="xmlui.Submission.submit.ReviewStep.submit_jump_files">Adicionar ou Excluir um arquivo</message> - <message key="xmlui.Submission.submit.ReviewStep.head1">Questões iniciais</message> - <message key="xmlui.Submission.submit.ReviewStep.head2">Descrever página {0}</message> - <message key="xmlui.Submission.submit.ReviewStep.head3">Arquivos enviados</message> - <message key="xmlui.Submission.submit.ReviewStep.multiple_titles">Vários tÃtulos</message> - <message key="xmlui.Submission.submit.ReviewStep.published_before">Publicado antes</message> - <message key="xmlui.Submission.submit.ReviewStep.no_metadata">-</message> - <message key="xmlui.Submission.submit.ReviewStep.unknown">Desconhecido</message> - <message key="xmlui.Submission.submit.ReviewStep.known">Conhecido</message> - <message key="xmlui.Submission.submit.ReviewStep.supported">Válido</message> - - <!-- org.dspace.app.xmlui.Submission.submit.CCLicenseStep --> - <message key="xmlui.Submission.submit.CCLicenseStep.ccws_error">Ocorreu um erro ... {0}</message> - <message key="xmlui.Submission.submit.CCLicenseStep.head">Licenciar seu trabalho</message> - <message key="xmlui.Submission.submit.CCLicenseStep.info1">Se você desejar, você pode adicionar um <a href="http://creativecommons.org/">Creative Commons</a> Licença para o seu item. <strong>As licenças Creative Commons determinam o que as pessoas que lêem o seu trabalho poderá fazer com ele.</strong></message> - <message key="xmlui.Submission.submit.CCLicenseStep.submit_choose_creative_commons">Escolha uma licença</message> - <message key="xmlui.Submission.submit.CCLicenseStep.submit_to_creative_commons">Ir para o site do Creative Commons para selecionar uma licença</message> - <message key="xmlui.Submission.submit.CCLicenseStep.license">Tipo de licença</message> - <message key="xmlui.Submission.submit.CCLicenseStep.select_change">Escolha ou altere sua licença...</message> - <message key="xmlui.Submission.submit.CCLicenseStep.no_license">Nenhuma licença Creative Commons</message> - <message key="xmlui.Submission.submit.CCLicenseStep.save_changes">Você deve clicar em Avançar para salvar as alterações.</message> - - <!-- org.dspace.app.xmlui.Submission.submit.LicenseStep --> - <message key="xmlui.Submission.submit.LicenseStep.head">Licença distribuÃda</message> - <message key="xmlui.Submission.submit.LicenseStep.info1"><strong>Há um último passo:</strong> Nesta Biblioteca Digital, para reproduzir, traduzir e distribuir sua submissão em todo o mundo, você deve concordar com os termos a seguir.</message> - <message key="xmlui.Submission.submit.LicenseStep.info2">Conceder a licença de distribuição padrão, selecionando "Eu concedo a Licença" e clique em "Finalizar submissão".</message> - <message key="xmlui.Submission.submit.LicenseStep.info3">Se você tiver dúvidas sobre esta licença, por favor entre em contato com os administradores do sistema.</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_label">Licença distribuÃda</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_checkbox">Eu concedo a licença</message> - <message key="xmlui.Submission.submit.LicenseStep.decision_error">Você deve conceder esta licença para completar a sua submissão. Se você é incapaz de conceder esta licença, poderá salvar o seu trabalho e retornar mais tarde ou Excluir a submissão clicando no botão 'Salvar e Sair' no botão abaixo.</message> - - <!-- org.dspace.app.xmlui.Submission.submit.RemovedStep --> - <message key="xmlui.Submission.submit.RemovedStep.head">Submissão removida</message> - <message key="xmlui.Submission.submit.RemovedStep.info1">Sua submissão foi removida e o item incompleto foi retirado do sistema.</message> - <message key="xmlui.Submission.submit.RemovedStep.go_submission">Ir para página de submissões</message> - - <!-- org.dspace.app.xmlui.Submission.submit.CompletedStep --> - <message key="xmlui.Submission.submit.CompletedStep.head">Submissão completa</message> - <message key="xmlui.Submission.submit.CompletedStep.info1">Sua coleção seguirá para o processo de revisão para esta coleção. Você receberá por e-mail uma notificação assim que sua submissão for incluÃda na coleção, ou caso tenha algum problema com o seu envio. Você também pode verificar o status da sua submissão, visitando sua página de submissões.</message> - <message key="xmlui.Submission.submit.CompletedStep.go_submission">Ir para página de submissões</message> - <message key="xmlui.Submission.submit.CompletedStep.submit_again">Submeter outro item</message> - - <!-- org.dspace.app.xmlui.Submission.workflow.PerformTaskStep --> - <message key="xmlui.Submission.workflow.PerformTaskStep.info1">Ações que você pode realizar nesta tarefa:</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.take_help">Atribuir esta tarefa para você mesmo.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.take_submit">Fazer a tarefa</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.leave_help">Deixar esta tarefa no conjunto para que outra pessoa faça.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.leave_submit">Fazer a tarefa</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.approve_help">Se você tiver revisado o item e ele é adequado para a inclusão na coleção, selecione "Aprovar".</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.approve_submit">Aprovar item</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.commit_help">Uma vez editado o item, utilize esta opção para publicá-lo.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.commit_submit">Publicar</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.reject_help">Se você revisou o item e não estiver <strong>not</strong> adequado para a inclusão na Coleção, selecione "Rejeitar". Em seguida, será solicitado que digite uma mensagem indicando o motivo do item não ser adequado, e se o solicitante deve mudar alguma coisa e que reenvie.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.reject_submit">Rejeitar o item</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.edit_help">Selecione esta opção para alterar os metadados do item.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.edit_submit">Editar metadado</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.return_help">Retornar esta tarefa para o conjunto para que outra pessoa possa executar.</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.return_submit">Retornar tarefa para o conjunto</message> - - <!-- org.dspace.app.xmlui.Submission.workflow.RejectTaskStep --> - <message key="xmlui.Submission.workflow.RejectTaskStep.info1">Por favor, digite o motivo da rejeição da submissão na caixa abaixo, indicando se o submetedor pode corrigir um problema e que reenvie.</message> - <message key="xmlui.Submission.workflow.RejectTaskStep.reason">Motivo</message> - <message key="xmlui.Submission.workflow.RejectTaskStep.reason_required">O campo motivo é obrigatório </message> - <message key="xmlui.Submission.workflow.RejectTaskStep.submit_reject">Rejeitar item</message> - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Administrative Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - <!-- action-generated messages. These are referenced from the sitemap rather than a transformer --> - - <message key="xmlui.administrative.FlowCurationUtils.curate_success_notice">A tarefa foi concluÃda com êxito.</message> - <message key="xmlui.administrative.FlowCurationUtils.curate_failed_notice">A tarefa foi interrompida inesperadamente. Para mais informações, por favor entre em contato com o administrador do site ou verifique os logs do seu sistema.</message> - <message key="xmlui.administrative.FlowCurationUtils.queue_success_notice">A tarefa foi colocada na sequência com sucesso.</message> - <message key="xmlui.administrative.FlowCurationUtils.queue_failed_notice">A tarefa não pode ser colocada na sequência. Ocorreu um erro. Para mais informações, por favor entre em contato com o administrador do site ou verifique os logs do seu sistema.</message> - <message key="xmlui.administrative.FlowEPersonUtils.add_eperson_success_notice">O usuário foi adicionado com sucesso.</message> - <message key="xmlui.administrative.FlowEPersonUtils.edit_eperson_success_notice">O usuário foi editado com sucesso.</message> - <message key="xmlui.administrative.FlowEPersonUtils.reset_password_success_notice">Uma mensagem de e-mail foi enviada para o usuário contendo uma referência que pode ser usada para escolher uma nova senha.</message> - <message key="xmlui.administrative.FlowEPersonUtils.delete_eperson_success_notice">O usuário(s) foi deletado com sucesso.</message> - <message key="xmlui.administrative.FlowEPersonUtils.delete_eperson_failed_notice">O usuário(s) listado(s) não foi excluÃdo porque há restrições que impedem a exclusão. Consulte a página de detalhes ePerson para mais informações.</message> - <message key="xmlui.administrative.FlowGroupUtils.edit_group_success_notice">O grupo foi editado com sucesso.</message> - <message key="xmlui.administrative.FlowGroupUtils.delete_group_success_notice">Os grupos selecionados foram excluÃdos com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.add_metadata_schema_success_notice">Novo esquema foi criado com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_metadata_schema_success_notice">O(s) esquema(s) foi excluÃdo com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.add_metadata_field_success_notice">O campo de metadado foi adicionado com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.edit_metadata_field_success_notice">O campo de metadado foi editado com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.move_metadata_field_success_notice">O(s) campo(s) foi alterado com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_metadata_field_success_notice">O(s) campo(s) foi excluÃdo com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.edit_bitstream_format_success_notice">O formato foi salvo com sucesso.</message> - <message key="xmlui.administrative.FlowRegistryUtils.delete_bitstream_format_success_notice">O(s) formato(s) foi excluÃdo com sucesso.</message> - <message key="xmlui.administrative.FlowItemUtils.metadata_updated">O metadado do item foi atualizado com sucesso.</message> - <message key="xmlui.administrative.FlowItemUtils.metadata_added">Novo metadado foi adicionado.</message> - <message key="xmlui.administrative.FlowItemUtils.item_withdrawn">O item foi removido.</message> - <message key="xmlui.administrative.FlowItemUtils.item_reinstated">O item foi reintegrado.</message> - <message key="xmlui.administrative.FlowItemUtils.item_moved">O item foi alterado.</message> - <message key="xmlui.administrative.FlowItemUtils.item_move_failed">O local da coleção selecionada não foi encontrado. </message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_added">O novo bitstream foi carregado com sucesso.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_failed">Erro ao carregar arquivo.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_updated">O bitstream foi atualizado.</message> - <message key="xmlui.administrative.FlowItemUtils.bitstream_delete">Os bitstreams selecionados foram excluÃdos.</message> - <message key="xmlui.administrative.FlowMapperUtils.map_items">Os itens foram mapeados com êxito.</message> - <message key="xmlui.administrative.FlowMapperUtils.unmaped_items">Os itens não foram mapeados.</message> - - <!-- general items for all of the eperson classes --> - <message key="xmlui.administrative.eperson.general.epeople_trail">Gerenciar e-people</message> - - <!-- org.dspace.app.xmlui.administrative.Navigation --> - <!-- contextual menu items --> - <message key="xmlui.administrative.Navigation.context_head">Contexto</message> - <message key="xmlui.administrative.Navigation.context_edit_item">Editar este item</message> - <message key="xmlui.administrative.Navigation.context_edit_collection">Editar coleção</message> - <message key="xmlui.administrative.Navigation.context_item_mapper">Mapear item</message> - <message key="xmlui.administrative.Navigation.context_edit_community">Editar comunidade</message> - <message key="xmlui.administrative.Navigation.context_create_collection">Criar coleção</message> - <message key="xmlui.administrative.Navigation.context_create_subcommunity">Criar subcomunidade</message> - <message key="xmlui.administrative.Navigation.context_create_community">Criar comunidade</message> - <message key="xmlui.administrative.Navigation.context_export_item">Item exportado</message> - <message key="xmlui.administrative.Navigation.context_export_collection">Exportar coleção</message> - <message key="xmlui.administrative.Navigation.context_export_community">Exportar comunidade</message> - <message key="xmlui.administrative.Navigation.context_export_metadata">Exportar metadado</message> - - <!-- 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_groups">Grupos</message> - <message key="xmlui.administrative.Navigation.administrative_authorizations">Autorizações</message> - <message key="xmlui.administrative.Navigation.administrative_registries">Registros</message> - <message key="xmlui.administrative.Navigation.administrative_metadata">Metadado</message> - <message key="xmlui.administrative.Navigation.administrative_format">Formato</message> - <message key="xmlui.administrative.Navigation.administrative_items">Itens</message> - <message key="xmlui.administrative.Navigation.administrative_withdrawn">Itens removidos</message> - <message key="xmlui.administrative.Navigation.administrative_private">Itens restritos</message> - <message key="xmlui.administrative.Navigation.administrative_control_panel">Painel de controle</message> - <message key="xmlui.administrative.Navigation.statistics">EstatÃsticas</message> - <message key="xmlui.administrative.Navigation.administrative_import_metadata">Importar metadado</message> - <message key="xmlui.administrative.Navigation.administrative_curation">Tarefas do revisor</message> - - <!-- my account items --> - <message key="xmlui.administrative.Navigation.account_export">Minhas exportações</message> - - - <!-- export item --> - <message key="xmlui.administrative.ItemExport.head">Exportar arquivo</message> - <message key="xmlui.administrative.ItemExport.item.id.error">O ID do item fornecido é inválido.</message> - <message key="xmlui.administrative.ItemExport.collection.id.error">O ID da coleção fornecido é inválido.</message> - <message key="xmlui.administrative.ItemExport.community.id.error">O ID da comunidade fornecido é inválido</message> - <message key="xmlui.administrative.ItemExport.item.not.found">O item solicitado não foi encontrado.</message> - <message key="xmlui.administrative.ItemExport.collection.not.found">A coleção solicitada não foi encontrada.</message> - <message key="xmlui.administrative.ItemExport.community.not.found">A comunidade solicitada não foi encontrada.</message> - <message key="xmlui.administrative.ItemExport.item.success">O item foi exportado com sucesso. Você receberá um e-mail quando o arquivo estiver pronto para download. Você também pode usar o link "Minhas exportações" para ver a lista dos arquivos disponÃveis.</message> - <message key="xmlui.administrative.ItemExport.collection.success">A coleção foi exportada com sucesso. Você receberá um e-mail quando o arquivo estiver pronto para download. Você também pode usar o link "Minhas exportações" para ver a lista dos arquivos disponÃveis.</message> - <message key="xmlui.administrative.ItemExport.community.success">A comunidade foi exportada com sucesso. Você receberá um e-mail quando o arquivo estiver pronto para download. Você também pode usar o link "Minhas exportações" para ver a lista dos arquivos disponÃveis.</message> - <message key="xmlui.administrative.ItemExport.available.head">Arquivos exportados disponÃveis para download:</message> - - - - <!-- org.dspace.app.xmlui.administrative.eperson.ManageEPeopleMain --> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.title">Gerenciar e-people</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.main_head">Gestão do e-person</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_head">Ações</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_create">Criar um novo e-person</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_create_link">Clique aqui para adicionar um novo e-person.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_browse">Buscar e-people</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_browse_link">Clique aqui para buscar todos os e-people.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.actions_search">Buscar por e-people</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_help">E-people são pesquisados por qualquer correspondência parcial no e-mail ou nome</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_para1">Abaixo segue a lista de e-people correspondente à sua pesquisa. Selecione a e-people que deseja excluir e clique no botão Excluir para continuar ou clique no e-mail ou nome da e-person para editá-los.</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_head">Resultados da busca</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column1"></message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column2">ID</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column3">Nome</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.search_column4">E-mail</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.submit_delete">Excluir e-people</message> - <message key="xmlui.administrative.eperson.ManageEPeopleMain.no_results">Sua busca não encontrou resultados...</message> - - - <!-- org.dspace.app.xmlui.administrative.eperson.AddEPersonForm --> - <message key="xmlui.administrative.eperson.AddEPersonForm.title">Adicionar e-person</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.trail">Adicionar e-person</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.head1">Criar um novo usuário</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.email_taken">Este endereço de e-mail já está em uso por outra e-person. Os e-mails devem ser únicos.</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.head2">Nova informação da e-person:</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_email_unique">O endereço de e-mail deve ser único</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_email">O endereço de e-mail é necessário</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_fname">Primeiro nome é necessário</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.error_lname">último nome é necessário</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.req_certs">Requer certificado</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.can_log_in">Pode entrar</message> - <message key="xmlui.administrative.eperson.AddEPersonForm.submit_create">Criar e-person</message> - - <!-- org.dspace.app.xmlui.administrative.eperson.EditEPersonForm --> - <message key="xmlui.administrative.eperson.EditEPersonForm.title">Editar e-person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.trail">Editar e-person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.head1">Editar e-person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.email_taken">Este endereço de e-mail já está em uso por outra e-person. Os e-mails devem ser únicos.</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.head2">{0}'s informação:</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_email_unique">O endereço de e-mail deve ser único</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_email">O endereço de e-mail é necessário</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_fname">Primeiro nome é necessário</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.error_lname">último nome é necessário</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.req_certs">Requer certificado</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.can_log_in">Pode entrar</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_reset_password">Alterar senha</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.special_help">Você também pode excluir permanentemente esta e-person do sistema ou redefinir sua senha. Ao redefinir a senha do usuário será enviado um e-mail contendo um link especial para escolher uma nova senha.</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_delete">Excluir e-person</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.submit_login_as">Entrar como e-person</message> - - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint">Esta e-person não pode ser excluÃdo por causa da restrição abaixo:</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.last_conjunction">e</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.item">E-person submeteu um ou mais itens</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.workflowitem">E-person tem um fluxo de trabalho para submissão ativo</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.tasklistitem">E-person tem uma tarefa no fluxo de trabalho aguardando revisão</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.delete_constraint.unknown">E-person tem uma restrição não identificada no interior do sistema</message> - - <message key="xmlui.administrative.eperson.EditEPersonForm.member_head">Este e-person é membro do grupo:</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.indirect_member">(via grupo: {0})</message> - <message key="xmlui.administrative.eperson.EditEPersonForm.member_none">nenhum</message> - - - <!-- org.dspace.app.xmlui.administrative.eperson.DeleteEPeopleConfirm --> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.title">Confirmar exclusão de e-person</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.trail">Confirmar exclusão</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.confirm_head">Confirmar exclusão</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.confirm_para">A seguinte e-people será excluÃda: </message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.submit_confirm">Confirmar exclusão</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_id">ID</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_name">Nome</message> - <message key="xmlui.administrative.eperson.DeleteEPeopleConfirm.head_email">E-mail</message> - - <!-- general items for all of the group classes --> - <message key="xmlui.administrative.group.general.group_trail">Gerenciar grupos</message> - - <!-- org.dspace.app.xmlui.administrative.group.ManageGroupsMain --> - <message key="xmlui.administrative.group.ManageGroupsMain.title">Gerenciar grupos</message> - <message key="xmlui.administrative.group.ManageGroupsMain.main_head">Grupo gerenciado</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_head">Ações</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_create">Criar um novo grupo</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_create_link">Clique aqui para adicionar um novo grupo.</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_browse">Buscar grupos</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_browse_link">Clique aqui para buscar todos os grupos.</message> - <message key="xmlui.administrative.group.ManageGroupsMain.actions_search">Buscar por grupos</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_help">Os grupos são pesquisados por qualquer correspondência parcial em seu nome</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_head">Resultados da busca</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column1"></message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column2">ID</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column3">Nome</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column4">Membros</message> - <message key="xmlui.administrative.group.ManageGroupsMain.search_column5">Comunidade/ Coleção</message> - <message key="xmlui.administrative.group.ManageGroupsMain.collection_link">Ver</message> - <message key="xmlui.administrative.group.ManageGroupsMain.submit_delete">Excluir grupos</message> - <message key="xmlui.administrative.group.ManageGroupsMain.no_results">Sua busca não encontrou resultados...</message> - - <!-- org.dspace.app.xmlui.administrative.group.EditGroupForm --> - <message key="xmlui.administrative.group.EditGroupForm.title">Grupo Editor</message> - <message key="xmlui.administrative.group.EditGroupForm.trail">Editar grupo</message> - <message key="xmlui.administrative.group.EditGroupForm.main_head">Grupo editor: {0} (id: {1})</message> - <message key="xmlui.administrative.group.EditGroupForm.main_head_new">Grupo Editor: novo grupo</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_clear">Limpar busca</message> - <message key="xmlui.administrative.group.EditGroupForm.member">Membro</message> - <message key="xmlui.administrative.group.EditGroupForm.cycle">Ciclo</message> - <message key="xmlui.administrative.group.EditGroupForm.pending">Pendente</message> - <message key="xmlui.administrative.group.EditGroupForm.pending_warn">Atenção, as alterações pendentes não são salvas até que você clique no botão Salvar.</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_add">Adicionar</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_remove">Excluir</message> - <message key="xmlui.administrative.group.EditGroupForm.collection_para">O grupo está relacionado com a coleção: </message> - <message key="xmlui.administrative.group.EditGroupForm.community_para">O grupo está relacionado com a comunidade: </message> - <message key="xmlui.administrative.group.EditGroupForm.label_name">Alterar nome do grupo: </message> - <message key="xmlui.administrative.group.EditGroupForm.label_instructions">O grupo está relacionado com uma coleção ou comunidade especÃfica e o nome não pode ser alterado.</message> - <message key="xmlui.administrative.group.EditGroupForm.label_search">Buscar membros para adicionar: </message> - <message key="xmlui.administrative.group.EditGroupForm.submit_search_people">E-people...</message> - <message key="xmlui.administrative.group.EditGroupForm.submit_search_groups">Grupos...</message> - <message key="xmlui.administrative.group.EditGroupForm.no_results">Sua busca não encontrou resultados...</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column2">Nome</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column3">E-mail</message> - <message key="xmlui.administrative.group.EditGroupForm.epeople_column4"></message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column2">Nome</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column3">Membros</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column4">Coleção</message> - <message key="xmlui.administrative.group.EditGroupForm.groups_column5"></message> - <message key="xmlui.administrative.group.ManageGroupsMain.groups_collection_link">ver</message> - <message key="xmlui.administrative.group.EditGroupForm.members_head">Membros</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column1">ID</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column2">Nome</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column3">E-mail</message> - <message key="xmlui.administrative.group.EditGroupForm.members_column4"></message> - <message key="xmlui.administrative.group.EditGroupForm.members_group_name">grupo: {0}</message> - <message key="xmlui.administrative.group.EditGroupForm.members_none">Este grupo não tem membros.</message> - <message key="xmlui.administrative.group.EditGroupForm.members_pending">[pendente]</message> - <message key="xmlui.administrative.group.EditGroupForm.instructions_para">Excluir membros</message> - <message key="xmlui.administrative.group.EditGroupForm.collection_link_para">Excluir membros</message> - - <!-- org.dspace.app.xmlui.administrative.group.DeleteGroupsConfirm --> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.title">Confirmar exclusão do grupo</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.trail">Confirmar exclusão</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.head">Confirmar exclusão</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.para">Os seguintes grupos serão excluÃdos:</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column1">ID</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column2">Nome</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column3">E-people</message> - <message key="xmlui.administrative.group.DeleteGroupsConfirm.column4">Grupos</message> - - <!-- general items for all of the registries classes --> - <message key="xmlui.administrative.registries.general.format_registry_trail">Formatar registro</message> - <message key="xmlui.administrative.registries.general.metadata_registry_trail">Registro do metadado</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.java --> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.title">Excluir formatos Bitstream</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.trail">Excluir formatos bitstream</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.head">Confirmar exclusão</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.para1">Você tem certeza que deseja excluir o formato? Quaisquer bitstreams existentes neste formato serão alterados para formatos bitstream desconhecidos.</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column2">MIME Type</message> - <message key="xmlui.administrative.registries.DeleteBitstreamFormatsConfirm.column3">Nome</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteMetadataFieldsConfirm.java --> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.title">Excluir campos</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.trail">Excluir campos</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.head">Confirmar exclusão</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.para1">Você tem <b>absoluta</b> certeza que deseja excluir estes campos? Se algum desses itens contém metadados para esses campos, o(s) campo(s) não poderá ser excluÃdo. Você deve ter certeza que nenhum desses itens utiliza esses campos.</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.warning">ATENçãO: </message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.para2">Isto causará um erro se qualquer item tiver metadados para esses campos.</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column2">Nome</message> - <message key="xmlui.administrative.registries.DeleteMetadataFieldsConfirm.column3">Nota de escopo</message> - - <!-- org.dspace.app.xmlui.administrative.registries.DeleteMetadataSchemaConfirm.java--> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.title">Excluir esquema</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.trail">Excluir esquema</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.head">Confirmar exclusão</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.para1">Você tem <b>absoluta</b> certeza que deseja excluir este esquema? Se algum desses itens contém metadados para esses campos deste esquema, este não pode ser excluÃdo. Você deve ter certeza que nenhum desses itens contém metadados neste esquema.</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.warning">ATENÇãO: </message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.para2">Isto causará um erro se qualquer item tiver metadados para esse esquema.</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column1">ID</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column2">Namespace</message> - <message key="xmlui.administrative.registries.DeleteMetadataSchemaConfirm.column3">Nome</message> - - <!-- org.dspace.app.xmlui.administrative.registries.EditBitstreamFormat.java --> - <message key="xmlui.administrative.registries.EditBitstreamFormat.title">Formato bitstream</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.trail">Formato bitstream</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.head1">Novo formato bitstream</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.head2">Formato bitstream: {0}</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.para1">Fornecer metadados descritivos sobre o formato bitstream abaixo. Enquanto os nomes dos formatos deverão ser únicos, para os MIME types não precisa. Você deverá separá as entradas dos formatos do registro para diferentes versões do Microsoft Word, embora o MIME type for o mesmo para cada um deles.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name">Nome</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name_help">Um único nome para este formato, (por exemplo, Microsoft Word XP ou Microsoft Word 2000)</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.name_error">O campo nome é obrigatório.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.mimetype">MIME Type</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.mimetype_help">O MIME type associado à este formato, nãho tem que ser único.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.description">Descrição</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support">NÃvel de suporte</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_help">o nÃvel de suporte que a sua instituição promete para este formato.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_0">Desconhecido</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_1">Conhecido</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.support_2">Válido</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.internal">Interno</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.internal_help">Os formatos marcados como internos são invisÃveis aos usuários e utilizados para fins administrativos.</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.extensions">Extensão dos arquivos</message> - <message key="xmlui.administrative.registries.EditBitstreamFormat.extensions_help">As extensões são extensões dos arquivos que são usados para identificar automaticamente o formato dos arquivos enviados. Você pode inserir várias extensões para cada formato.</message> - - <!-- org.dspace.app.xmlui.administrative.registries.EditMetadataSchema.java --> - <message key="xmlui.administrative.registries.EditMetadataSchema.title">Esquema de metadados</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.trail">Esquema de metadados</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head1">Esquema de metadados: "{0}"</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.para1">Este é o esquema de metadados para "{0}". Você pode adicionar novos ou atualizar os campos de metadados existentes para esse esquema. Os campos podem também ser seleccionadas para exclusão ou ser movido para um outro esquema. </message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head2">Esquema de campo de metadado</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column1"></message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column2">ID</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column3">Campo</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.column4">Nota de escopo</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.empty">Sem campo de metadado</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_delete">Excluir campos</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_move">Mover campos para outro esquema</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head3">Adicionar novo campo de metadados</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.name">Nome do campo</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.note">Nota de escopo</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.note_help">Notas adicionais sobre este campo de metadados.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_add">Adicionar novo campo de metadados</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.head4">Atualização do campo: {0}</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.submit_update">Atualização do campo</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error">Erro</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_duplicate_field">O nome do campo já está em uso, todos os elementos qualificadores devem ser exclusivos.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_empty">O elemento do campo é necessário.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_badchar">O elemento do campo contém um caractere ruim. O elemento não pode conter: perÃodos, sublinhados ou espaços.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_element_tolong">O elemento do campo é longo, ele deve ser inferior a 32 caracteres.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_qualifier_tolong">O campo de qualificação é muito grande, ele deve ser inferior a 32 caracteres.</message> - <message key="xmlui.administrative.registries.EditMetadataSchema.error_qualifier_badchar">Qualificador do campo contém um caractere ruim. O qualificador NãO pode conter: perÃodos, sublinhados ou espaços.</message> - - <!-- org.dspace.app.xmlui.administrative.registries.FormatRegistryMain.java --> - <message key="xmlui.administrative.registries.FormatRegistryMain.title">Formatar registro</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.head">Registro de formato Bitstream</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.para1">Esta lista de formatos de bitstream fornece informações sobre os formatos conhecidos e seu nÃvel de apoio. Você pode editar ou adicionar novos formatos de bitstream com esta ferramenta. Formatos marcados como 'interno' são inivisÃveis ao usuário e são utilizados para fins administrativos.</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.new_link">Adicionar um novo formato bitstream</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column1"></message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column2">ID</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column3">Nome</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column4">Tipo MIME</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.column5">NÃvel de suporte</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.internal">(<i>interno</i>)</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_0">Desconhecido</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_1">Conhecido</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.support_2">Suporte</message> - <message key="xmlui.administrative.registries.FormatRegistryMain.submit_delete">Excluir formatos</message> - - <!-- org.dspace.app.xmlui.administrative.registries.MetadatRegistryMain.java --> - <message key="xmlui.administrative.registries.MetadataRegistryMain.title">Registro de metadado</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.head1">Registro de metadado</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.para1">O registro de metadados mantém uma lista de todos os campos de metadados disponÃveis no repositório. Estes campos podem ser divididos entre vários esquemas. No entanto, a Biblioteca Digital requer esquema do Dublin Core qualificado. Você pode estender o esquema Dublin Core com campos adicionais ou adicionar novos esquemas para o registro.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column1"></message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column2">ID</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column3">Namespace</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.column4">Nome</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.submit_delete">Excluir esquema</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.head2">Adicionar novo esquema</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace">Namespace</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace_help">Namespace deve ser um local URI estabelecida para o novo esquema.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.namespace_error">Este campo é necessário.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name">Nome</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name_help">Notação abreviada para o esquema. Isto irá ser utilizado para prefixo de nome de um campo (por exemplo, dc.element.qualifier). O nome deve ser inferior a 32 caracteres e não pode incluir espaços, perÃodos ou sublinhados.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.name_error">Este campo é obrigatório e deve ser inferior a 32 caracteres não pode conter espaços, pontos ou sublinhados.</message> - <message key="xmlui.administrative.registries.MetadataRegistryMain.submit_add">Adicionar novo esquema</message> - - <!-- org.dspace.app.xmlui.administrative.registries.MoveMetadataField.java --> - <message key="xmlui.administrative.registries.MoveMetadataField.title">Mover campos</message> - <message key="xmlui.administrative.registries.MoveMetadataField.trail">Mover campos</message> - <message key="xmlui.administrative.registries.MoveMetadataField.head1">Mover campos de metadados</message> - <message key="xmlui.administrative.registries.MoveMetadataField.para1">Selecione um esquema de destino onde esses campos serão movidos. Se o esquema de destino já possui campos com nomes idênticos, os campos não serão movidos.</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column1">ID</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column2">Nome</message> - <message key="xmlui.administrative.registries.MoveMetadataField.column3">Nota escopo</message> - <message key="xmlui.administrative.registries.MoveMetadataField.para2">Mover para o esquema: </message> - <message key="xmlui.administrative.registries.MoveMetadataField.submit_move">Mover campos</message> - - - - - <!-- general authorization keywords --> - <message key="xmlui.administrative.authorization.general.authorize_trail">Autorização</message> - <message key="xmlui.administrative.authorization.general.policyList_trail">Listar polÃticas</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.AuthorizationMain --> - <message key="xmlui.administrative.authorization.AuthorizationMain.title">Administrar polÃticas de autorização</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.main_head">Administrar polÃticas de autorização</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_head">Autorizações do item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.bad_name">O a sequencia ID que você forneceu não contempla um item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_item_lookup">Buscar um item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.search_help">Os itens podem ser encontrados por handle ou ID interno</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.submit_find">Encontrar</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_advanced">Ferramenta para autorizações avançadas</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.actions_advanced_link">Clique aqui para ir para a ferramenta de administração de polÃtica universal do item</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.containerList_head">Altorizações de comunidade / coleção</message> - <message key="xmlui.administrative.authorization.AuthorizationMain.containerList_para">Clique em uma comunidade ou coleção para editar as suas polÃticas.</message> - - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditContainerPolicies --> - <message key="xmlui.administrative.authorization.EditContainerPolicies.title">Editar polÃtica</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.trail">Listar polÃticas</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_head_collection">PolÃticas para a coleção "{0}" ({1},ID: {2})</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_head_community">PolÃticas para a comunidade "{0}" ({1},ID: {2})</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.main_add_link">Clique aqui para adicionar nova polÃtica. </message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.submit_add">Adicionar</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_id">ID</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_name">Nome</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_action">Ação</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_group">Grupo</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_start_date">Data inicial</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.head_end_date">Data final</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.submit_delete">Selecionar exclusão</message> - <message key="xmlui.administrative.authorization.EditContainerPolicies.group_edit">Editar</message> - - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditItemPolicies --> - <message key="xmlui.administrative.authorization.EditItemPolicies.title">Editar polÃtica do item</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.trail">Listar polÃticas</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_head">PolÃtica do item {0} (ID={1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_para1">Com este editor você pode visualizar e alterar as polÃticas de um item, além de alterar as polÃticas de componentes de itens individuais: pacotes e bitstreams. Resumidamente, um item é um recipiente de bundles, e bundles são recipientes de bitstreams. Recipientes geralmente têm ADICIONAR / Excluir / LER / ESCREVER polÃticas, enquanto bitstreams sótem polÃticas de leitura / gravação.</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.main_para2">Você vai notar um bundle extra e bitstream para cada item que contém o texto da licença para o item.</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_item">PolÃtica do item</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_bundle">PolÃtica para Bundle {0} ({1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.subhead_bitstream">Bitstream {0} ({1})</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_itemPolicy_link">Adicionar uma nova polÃtica para o item</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_bundlePolicy_link">Adicionar uma nova polÃtica para o bundle</message> - <message key="xmlui.administrative.authorization.EditItemPolicies.add_bitstreamPolicy_link">Adicionar uma nova polÃtica para o bitstream</message> - - <message key="xmlui.administrative.authorization.EditContainerPolicies.no_policies">Nenhuma polÃtica encontrada para este objeto.</message> - - - <!-- org.dspace.app.xmlui.administrative.authorization.EditPolicyForm --> - <message key="xmlui.administrative.authorization.EditPolicyForm.title">Editar polÃtica</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.trail">Editar polÃtica</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.main_head_new">Criar nova polÃtica para {0} {1}</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.main_head_edit">Editar polÃtica {0} para {1} {2}</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_no_group">Grupo não selecionado</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_no_action">Ação não selecionada</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column4"></message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column1">ID</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column2">Nome</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_column3">Ações para este recurso</message> - - <message key="xmlui.administrative.authorization.EditPolicyForm.set_group">Conjunto</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.current_group">atual</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.groups_head">Resultado da busca</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.policy_currentGroup">Selecionar um grupo</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_search">Buscar um grupo</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.submit_search_groups">Buscar</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_action">Selecionar a ação</message> - - <message key="xmlui.administrative.authorization.EditPolicyForm.label_name">Nome</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_description">Descrição</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_start_date">Data inicial</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_end_date">Data final</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_date_format">Data inválida</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_duplicated_policy">Uma polÃtica identica ao grupo e essa ação está vigente.</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.error_start_date_greater_than_end_date">Data inicial maior que a data final</message> - <message key="xmlui.administrative.authorization.EditPolicyForm.label_date_help">Formato de data aceitável: yyyy (ano), yyyy-mm (ano e mês), yyyy-mm-dd (ano, mês e dia)</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.AdvacedAuthorizationsForm --> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.title">Gestão avançada da polÃtica</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.trail">Autorizações avançadas</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.main_head">Gestão avançada da polÃtica</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.main_para">Permite adições universais para adição e compensação de polÃticas para os tipos de conteúdo dentro de coleção(es) especÃfica (s). AVISO - removendo permissões de LEITURA a partir de itens irá torná-los não visÃveis!</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_groupSentence">Para todos os grupos selecionados...</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_actionSentence">...conceder a capacidade de executar a seguinte ação...</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_resourceSentence">...para todos os tipos de objetos seguintes...</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_collectionSentence">...através das seguintes coleções.</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyGroup">Grupo</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyAction">Ação</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyResource">Tipo de conteúdo</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_policyCollections">Coleção</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.submit_add">Adicionar polÃtica</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.submit_remove_all">Excluir polÃtica</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.label_date_help">Formato de data aceitável: yyyy (ano), yyyy-mm (ano e mês), yyyy-mm-dd (ano, mês e dia)</message> - - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_name">Nome</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_description">Descrição</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_start_date">Data inicial</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.actions_end_date">Data final</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_date_format">Data inválida</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_start_date_greater_than_end_date">Data inicial maior que a data final</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_groupIds">Selecione pelo menos um grupo</message> - <message key="xmlui.administrative.authorization.AdvancedAuthorizationsForm.error_collectionIds">Selecione pelo menos uma coleção</message> - - <!-- org.dspace.app.xmlui.administrative.authorization.DeletePoliciesConfirm --> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.title">Confirmar exclusão da polÃtica</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.trail">Confirmar exclusão</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.confirm_head">Confirmar exclusão</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.confirm_para">As polÃticas a seguir serão removidas: </message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_id">ID</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_action">Ação</message> - <message key="xmlui.administrative.authorization.DeletePoliciesConfirm.head_group">Grupo</message> - - <!-- general edit item messages --> - <message key="xmlui.administrative.item.general.item_trail">Itens</message> - <message key="xmlui.administrative.item.general.template_head">Editar item modelo para coleção: {0}</message> - <message key="xmlui.administrative.item.general.option_head">Editar item</message> - <message key="xmlui.administrative.item.general.option_status">Estado do item</message> - <message key="xmlui.administrative.item.general.option_bitstreams">Item Bitstreams</message> - <message key="xmlui.administrative.item.general.option_metadata">Metadado do item</message> - <message key="xmlui.administrative.item.general.option_view">Vizualização do item</message> - <message key="xmlui.administrative.item.general.option_curate">Atual</message> - <message key="xmlui.administrative.item.general.option_queue">Queue</message> - - <!-- org.dspace.app.xmlui.administrative.item.AddBitstreamForm --> - <message key="xmlui.administrative.item.AddBitstreamForm.title">Upload Bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.trail">Upload bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.head1">Upload de um novo bitstream</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle_label">Bundle</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.ORIGINAL">Arquivos de Conteúdo (padrão)</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.METADATA">Arquivos de metadados</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.THUMBNAIL">Miniaturas</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.LICENSE">Licença</message> - <message key="xmlui.administrative.item.AddBitstreamForm.bundle.CC-LICENSE">Licenças Creative Commons</message> - <message key="xmlui.administrative.item.AddBitstreamForm.file_label">Arquivo</message> - <message key="xmlui.administrative.item.AddBitstreamForm.file_help">Por favor, insira o nome do arquivo no seu computador correspondente ao seu item. Se você clicar em "Buscar ...", uma nova janela aparecerá na qual você poderá localizar e selecionar o arquivo do seu computador.</message> - <message key="xmlui.administrative.item.AddBitstreamForm.description_label">Descrição</message> - <message key="xmlui.administrative.item.AddBitstreamForm.description_help">Opcionalmente, fornecer uma breve descrição do arquivo, por exemplo "<i>Artigo principal</i>", or "<i>Leitura de metadados</i>".</message> - <message key="xmlui.administrative.item.AddBitstreamForm.submit_upload">Upload</message> - <message key="xmlui.administrative.item.AddBitstreamForm.no_bundles">Você precisa adicionar e ESCREVA privilégio em pelo menos um bundle de ser capaz de carregar bitstreams novos.</message> - - <!-- org.dspace.app.xmlui.administrative.item.DeleteBitstreamConfirm --> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.title">Confirmar exclusão</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.trail">Confirmar exclusão</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.head1">Confirmar exclusão(es)</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.para1">Tem certeza de que deseja excluir estes bitstreams:</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column1">Nome</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column2">Descrição</message> - <message key="xmlui.administrative.item.DeleteBitstreamConfirm.column3">Formato</message> - - <!-- org.dspace.app.xmlui.administrative.item.ConfirmItemForm --> - <message key="xmlui.administrative.item.ConfirmItemForm.title">Confirmar</message> - <message key="xmlui.administrative.item.ConfirmItemForm.trail">Confirmar</message> - <message key="xmlui.administrative.item.ConfirmItemForm.head1">Modificar item: {0}</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_delete">Tem certeza que este item deve ser completamente eliminado? Atenção: No momento, nenhuma marca para exclusão será deixada.</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_withdraw">Tem certeza que este item deve ser retirado do arquivo?</message> - <message key="xmlui.administrative.item.ConfirmItemForm.para_reinstate">Tem certeza que este item deve ser reintegrado ao arquivo?</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column1">Campo</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column2">Valor</message> - <message key="xmlui.administrative.item.ConfirmItemForm.column3">Idioma</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_withdraw">Retirar</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_reinstate">Reintegrar</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_private">Tornar restrito</message> - <message key="xmlui.administrative.item.ConfirmItemForm.submit_public">Tornar público</message> - - <!-- org.dspace.app.xmlui.aspect.administrative.item.MoveItemForm --> - <message key="xmlui.administrative.item.MoveItemForm.title">Mover</message> - <message key="xmlui.administrative.item.MoveItemForm.trail">Mover</message> - <message key="xmlui.administrative.item.MoveItemForm.head1">Mover item: {0}</message> - <message key="xmlui.administrative.item.MoveItemForm.collection">Coleção</message> - <message key="xmlui.administrative.item.MoveItemForm.collection_help">Selecione a coleção que você deseja mover este item.</message> - <message key="xmlui.administrative.item.MoveItemForm.collection_default">Selecione uma coleção...</message> - <message key="xmlui.administrative.item.MoveItemForm.submit_move">Mover</message> - <message key="xmlui.administrative.item.MoveItemForm.inherit_policies">Manter polÃtica</message> - <message key="xmlui.administrative.item.MoveItemForm.inherit_policies_help">Manter as polÃticas padrão da coleção de destino</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditBitstreamForm --> - <message key="xmlui.administrative.item.EditBitstreamForm.title">Editar Bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.trail">Editar bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.head1">Editar Bitstream</message> - <message key="xmlui.administrative.item.EditBitstreamForm.file_label">Arquivo</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_label">Bitstream primário</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_option_yes">sim</message> - <message key="xmlui.administrative.item.EditBitstreamForm.primary_option_no">não</message> - <message key="xmlui.administrative.item.EditBitstreamForm.description_label">Descrição</message> - <message key="xmlui.administrative.item.EditBitstreamForm.description_help">Opcionalmente, fornecer uma breve descrição do arquivo, por exemplo "<i>Artigo principal</i>", ou "<i>Leitura de dados</i>"."</message> - <message key="xmlui.administrative.item.EditBitstreamForm.para1">Selecione o formato do arquivo a partir da lista abaixo, por exemplo "<i>Adobe PDF</i>" or "<i>Microsoft Word</i>", <b>ou</b> se o formato não está na lista, por favor descreva-o na caixa abaixo.</message> - <message key="xmlui.administrative.item.EditBitstreamForm.format_label">Formato selecionado</message> - <message key="xmlui.administrative.item.EditBitstreamForm.format_default">Formato não listado</message> - <message key="xmlui.administrative.item.EditBitstreamForm.para2">Se o formato não está na lista acima, <strong>selecione "Formato não consta na lista" acima</strong> e descreva-o no campo abaixo.</message> - <message key="xmlui.administrative.item.EditBitstreamForm.user_label">Outro formato</message> - <message key="xmlui.administrative.item.EditBitstreamForm.user_help">O aplicativo usado para criar o arquivo, e o número da versão (por exemplo, "<i>ACMESoft SuperApp version 1.5</i>").</message> - <message key="xmlui.administrative.item.EditBitstreamForm.name_label">Nome do arquivo:</message> - <message key="xmlui.administrative.item.EditBitstreamForm.name_help">Renomeie o arquivo para o bitstream. Note que isto irá mudar a exibição da URL bistream , mas links antigos ainda serão usados enquanto a sequencia ID não muda.</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemBitstreamsForm --> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.title">Item Bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.trail">Item bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.head1">Bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column1"></message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column2">Nome</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column3">Descrição</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column4">Formato</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column5">Vizualização</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column6">Ordem</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.column7"> </message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.bundle_label"><strong>Bundle: {0}</strong></message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.primary_label"> (primário) </message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.view_link">visualizar</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_add">Upload de novo bitstream</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_delete">Excluir bitstreams</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.submit_reorder">Atualização para bitstream</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.no_upload">Você precisa adicionar e ESCREVA privilégio sobre o item e bundles para ser capaz de carregar novos bitstreams.</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.no_remove">Apenas administradores do sistema podem excluir bitstreams / arquivos.</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.previous_order">Anterior:</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.order_up">Mover para cima</message> - <message key="xmlui.administrative.item.EditItemBitstreamsForm.order_down">Mover para baixo</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemMetadataForm --> - <message key="xmlui.administrative.item.EditItemMetadataForm.title">Metadado do item</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.trail">Metadado do item</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.head1">Adicionar novo metadado</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.name_label">Nome</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.value_label">Valor</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.lang_label">Idioma</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.submit_add">Adicionar novo metadado</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.para1">ATENçãO: Estas mudanças de alguma forma não são validados Você é responsável por inserir os dados no formato correto. Se você não tem certeza do que o formato é, por favor NãO faça alterações.</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.head2">Metadado</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column1">Excluir</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column2">Nome</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column3">Valor</message> - <message key="xmlui.administrative.item.EditItemMetadataForm.column4">Idioma</message> - - <!-- org.dspace.app.xmlui.administrative.item.EditItemStatusForm --> - <message key="xmlui.administrative.item.EditItemStatusForm.title">Estado do item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.trail">Estado do item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.para1">Bem-vindo à página de gerenciamento de item. A partir daqui você pode retirar, reintegrar, mover ou excluir o item. Você também pode atualizar ou adicionar novos metadados / bitstreams nas outras guias.</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_id">ID interno do item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_handle">Handle</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_modified">última modificação</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_in">Na coleção</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_page">Página do item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_auth">Editar polÃticas de autorização do item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_withdraw">Retirar item do repositório</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_reinstate">Reintegrar item no repositório</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_move">Mover o item para outra coleção</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_delete">Expurgar completamente o item</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_authorizations">Autorizações...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_withdraw">Retirar...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_reinstate">Restabelecer...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_move">Mover...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_delete">Excluir permanentemente</message> - <message key="xmlui.administrative.item.EditItemStatusForm.na">n/a</message> - <message key="xmlui.administrative.item.EditItemStatusForm.sysadmins_only">(só para administradores do sistema)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.collection_admins_only">(só para administradores da coleção)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.not_allowed">(você não tem permissão para executar esta ação)</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_private">Tornar restrito</message> - <message key="xmlui.administrative.item.EditItemStatusForm.label_public">Tornar público</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_private">Tornar restrito...</message> - <message key="xmlui.administrative.item.EditItemStatusForm.submit_public">Tornar público...</message> - - - - <!-- org.dspace.app.xmlui.administrative.item.ViewItem --> - <message key="xmlui.administrative.item.ViewItem.title">Visualizar item</message> - <message key="xmlui.administrative.item.ViewItem.trail">Visualizar item</message> - <!-- org.dspace.app.xmlui.administrative.item.CurateItemForm.java --> - <message key="xmlui.administrative.item.CurateItemForm.main_head">Atualizar item: {0}</message> - <message key="xmlui.administrative.item.CurateItemForm.title">Atualizar item</message> - <message key="xmlui.administrative.item.CurateItemForm.trail">Atualizar</message> - <message key="xmlui.administrative.item.CurateItemForm.label_name">Tarefa</message> - - <!-- org.dspace.app.xmlui.administrative.item.FindItemForm --> - <message key="xmlui.administrative.item.FindItemForm.title">Item encontrado</message> - <message key="xmlui.administrative.item.FindItemForm.head1">Item encontrado</message> - <message key="xmlui.administrative.item.FindItemForm.identifier_label">Item interno ID/Item Handle</message> - <message key="xmlui.administrative.item.FindItemForm.identifier_error">Não foi possÃvel determinar o identificador.</message> - <message key="xmlui.administrative.item.FindItemForm.find">Encontrar</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport --> - <message key="xmlui.administrative.metadataimport.general.title">Importar metadado</message> - <message key="xmlui.administrative.metadataimport.general.head1">Importar metadado</message> - <message key="xmlui.administrative.metadataimport.general.trail">Importar metadadp</message> - <message key="xmlui.administrative.metadataimport.general.changes">alteração</message> - <message key="xmlui.administrative.metadataimport.general.no_changes">Não foram detectadas alterações</message> - <message key="xmlui.administrative.metadataimport.general.new_item">Novo item</message> - <message key="xmlui.administrative.metadataimport.flow.upload_successful">Upload realizado com sucesso</message> - <message key="xmlui.administrative.metadataimport.flow.upload_failed">Falha no upload</message> - <message key="xmlui.administrative.metadataimport.flow.upload_badschema">Esquema de metadados do cabeçalho desconhecido</message> - <message key="xmlui.administrative.metadataimport.flow.upload_badelement">Elemento de metadado do cabeçalho desconhecido</message> - <message key="xmlui.administrative.metadataimport.flow.import_successful">Importação realizada com sucesso</message> - <message key="xmlui.administrative.metadataimport.flow.import_failed">Falha na importação</message> - <message key="xmlui.administrative.metadataimport.flow.over_limit">Número de alterações excede o máximo permitido.</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportConfirm --> - <message key="xmlui.administrative.metadataimport.MetadataImportMain.submit_upload">Upload CSV</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportConfirm --> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.success">Processado com sucesso</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.changes_committed">Alterações aplicadas no item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_added">Adicionar: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_removed">Excluir: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_newowner">Adicionar para obter coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_oldowner">Excluir para obter coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_mapped">Mapear coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.collection_unmapped">Não maperar coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_deleted">Item expurgado</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_withdrawn">Item retirado</message> - <message key="xmlui.administrative.metadataimport.MetadataImportConfirm.item_reinstated">Item restabelecido</message> - - <!-- org.dspace.app.xmlui.administrative.metadataimport.MetadataImportUpload --> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_add">Adicionar: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_remove">Excluir: </message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_newowner">Adicionar para obter coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_oldowner">Excluir para obter coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_mapped">Mapear coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.collection_unmapped">Não mapear coleção</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.changes_pending">Alterações pendentes do item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.submit_confirm">Aplicar alterações</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.hint">As alterações pendentes estão listados abaixo para revisão</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_delete">Expurgar item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_withdraw">Retirar item</message> - <message key="xmlui.administrative.metadataimport.MetadataImportUpload.item_reinstate">Restabelecer item</message> - - <!-- general mapper messages --> - <message key="xmlui.administrative.mapper.general.mapper_trail">Mapear item</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.MapperMain --> - <message key="xmlui.administrative.mapper.MapperMain.title">Mapear item</message> - <message key="xmlui.administrative.mapper.MapperMain.head1">Mapear item - Mapear item de outras coleções</message> - <message key="xmlui.administrative.mapper.MapperMain.para1">Coleção: "<strong>{0}</strong>"</message> - <message key="xmlui.administrative.mapper.MapperMain.para2">Esta é a ferramenta para mapear item que permite aos administradores de coleta mapear itens de outras coleções para esta coleção. Você pode buscar por itens de outras coleções e mapeá-los, ou navegar na lista de itens atualmente mapeados.</message> - <message key="xmlui.administrative.mapper.MapperMain.stat_label">EstatÃsiticas</message> - <message key="xmlui.administrative.mapper.MapperMain.stat_info"><strong>{0} de {1}</strong> itens desta coleção são mapeados a partir de outras coleções</message> - <message key="xmlui.administrative.mapper.MapperMain.search_label">Buscar</message> - <message key="xmlui.administrative.mapper.MapperMain.submit_search">Buscar itens</message> - <message key="xmlui.administrative.mapper.MapperMain.submit_browse">Buscar itens mapeados</message> - <message key="xmlui.administrative.mapper.MapperMain.no_add">(Requer que a coleção ADD privilégio)</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.SearchItemForm --> - <message key="xmlui.administrative.mapper.SearchItemForm.title">Buscar itens</message> - <message key="xmlui.administrative.mapper.SearchItemForm.trail">Buscar itens</message> - <message key="xmlui.administrative.mapper.SearchItemForm.head1">SBuscar itens relacionados: "{0}"</message> - <message key="xmlui.administrative.mapper.SearchItemForm.submit_map">Mapear itens selecionados</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column1"></message> - <message key="xmlui.administrative.mapper.SearchItemForm.column2">Coleção</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column3">Autor</message> - <message key="xmlui.administrative.mapper.SearchItemForm.column4">TÃtulo</message> - - <!-- org.dspace.app.xmlui.administrative.mapper.BrowseItemForm --> - <message key="xmlui.administrative.mapper.BrowseItemForm.title">Buscar itens mapeados</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.trail">Buscar itens mapeados</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.head1">Buscar itens mapeados</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.submit_unmap">Itens selecionados não mapeados</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column1"></message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column2">Coleção</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column3">Autor</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.column4">TÃtulo</message> - <message key="xmlui.administrative.mapper.BrowseItemForm.no_remove">Você precisa do privilégio REMOVE nesta coleção para ser capaz de não mapear itens desta coleção.</message> - - <!-- General tags for collection management --> - <message key="xmlui.administrative.collection.general.collection_trail">Coleções</message> - <message key="xmlui.administrative.collection.general.options_metadata">Editar metadados</message> - <message key="xmlui.administrative.collection.general.options_roles">Atribuir função</message> - <message key="xmlui.administrative.collection.general.options_curate">Atualizar</message> - <message key="xmlui.administrative.collection.general.options_queue">Queue</message> - - <!-- org.dspace.app.xmlui.administrative.collection.AssignCollectionRoles.java --> - <message key="xmlui.administrative.collection.AssignCollectionRoles.title">Editar a função da coleção</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.trail">Função</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.main_head">Editar coleção: {0}</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.no_role">nenhum</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.create">Criar...</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.restrict">Restringir...</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_admins">Administradores da coleção decidem quem pode submeter itens à coleção, editar metadados do item (após o envio) e adicionar (mapa) itens existentes de outras coleções para esta coleção (sujeita a autorização para esta coleção).</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step1">As pessoas responsáveis ??por esta etapa são capazes de aceitar ou rejeitar propostas recebidas. No entanto, eles não são capazes de editar metadados da submissão.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step2">As pessoas responsáveis ??por esta etapa são capazes de editar os metadados de submissões recebidas e então aceitar ou rejeitá-los.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_wf_step3">As pessoas responsáveis ??por esta etapa são capazes de editar os metadados de submissões recebidas, mas não serão capazes de rejeitá-los.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_submitters">Os e-people e grupos que têm permissão para submeter novos itens a esta coleção.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.help_default_read">E-people e Grupos que podem ler novos itens submetidos a essa coleção. Alterações nesta função não são retroativas. Itens existentes no sistema ainda vão ser vistos por aqueles que tinham acesso de leitura no momento de sua inclusão ao sistema.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.default_read_custom">Esta coleção usa as configurações personalizadas de acesso padrão. </message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.default_read_anonymous">Padrão de leitura para os itens de entrada e bitstreams está configurado para Anônimo.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.edit_authorization">Editar diretamente as polÃticas de autorização.</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_name">Função</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_group">Grupos associados</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.role_buttons"> </message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_admins">Administradores</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf">Passos do fluxo de submissão</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step1">Etapa Aceitar/Rejeitar</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step2">Etapa Aceitar/Rejeitar/Editar metadados</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_wf_step3">Etapa Editar Metadados</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_submitters">Submetedores</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.label_default_read">Padrão de acesso de leitura</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.sysadmins_only"><nobr>(sópara adminstradores do sistema)</nobr></message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.repository_role"><br/>(NÃvel de grupo do repositório, somente para administradores)</message> - <message key="xmlui.administrative.collection.AssignCollectionRoles.not_allowed"><nobr>(você não tem permissão para esta configuração)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.collection.CurateCollectionForm.java --> - <message key="xmlui.administrative.collection.CurateCollectionForm.main_head">Atualização da coleção: {0}</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.title">Atualização da coleção</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.trail">Atualização</message> - <message key="xmlui.administrative.collection.CurateCollectionForm.label_name">Tarefa</message> - - <!-- org.dspace.app.xmlui.administrative.collection.DeleteCollectionConfirm.java --> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.title">Confirmar exclusão</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.trail">Confirmar</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.main_head">Confirmar a exclusão da coleção {0}</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.main_para">Você tem certeza que a coleção {0} deve ser excluÃda? Isto excluirá:</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item1">Todos os itens e submissões incompletas nesta coleção que não estão inseridos em outras coleções</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item2">O conteúdo destes itens</message> - <message key="xmlui.administrative.collection.DeleteCollectionConfirm.confirm_item3">Todas as autorizações das polÃticas associadas</message> - - <!-- org.dspace.app.xmlui.administrative.collection.DeleteCollectionRoleConfirm.java --> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.title">Confirmar a exclução da função</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.trail">Confirmar</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_head">Confirmar a exclução da função {0}</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_para_read">Você tem certeza de que deseja excluir este papel? Excluindo este grupo dará acesso a todos os usuários de todos os itens apresentados a esta coleção a partir de agora. Por favor, note que essa mudança não é retroativa. Itens existentes no sistema ainda serão restritos aos membros definidos pelo função que você está prestes a excluir.</message> - <message key="xmlui.administrative.collection.DeleteCollectionRoleConfirm.main_para">Você tem certeza de que deseja excluir esta função? Todas as alterações e personalizações feitas ao grupo {0} serão perdidas e teriam de ser criadas novamente.</message> - - <!-- org.dspace.app.xmlui.administrative.collection.EditCollectionMetadataForm.java --> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.title">Editar metadado da coleção</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.trail">Metadado</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.main_head">Editar coleção: {0}</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_name">Nome</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_short_description">Pequena descrição</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_introductory_text">Texto introdutório (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_copyright_text">Texto sobre os direitos autorais (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_side_bar_text">NotÃcias (HTML)</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_license">Licença</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_provenance_description">Relação</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_logo">Upload de nova imagem</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_existing_logo">Atualização da imagem</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.label_item_template">Modelo de item</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_create_template">Criar...</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_edit_template">Editar...</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_delete_logo">Excluir imagem</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_delete">Excluir coleção</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.submit_save">Salvar atualizações</message> - <message key="xmlui.administrative.collection.EditCollectionMetadataForm.sysadmins_only"><nobr>(só para adminstradores do sistema)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.collection.CreateCollectionForm.java --> - <message key="xmlui.administrative.collection.CreateCollectionForm.title">Criação de coleção</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.trail">Criação de coleção</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.main_head">Informar metadado para uma nova coleção {0}</message> - <message key="xmlui.administrative.collection.CreateCollectionForm.submit_save">Criar</message> - - <!-- General to the harvesting options under collection --> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.title">Configurações da coleção de Harvesting </message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.trail">Harvesting</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.options_harvest">Fonte de conteúdo</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.label_source">Fonte de conteúdo</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_normal">Esta é uma coleção DSpace padrão</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.source_harvested">Esta coleção do harvest é de fonte externa de conteúdo</message> - <message key="xmlui.administrative.collection.GeneralCollectionHarvestingForm.submit_save">Salvar</message> - - <!-- org.dspace.app.xmlui.administrative.collection.SetupCollectionHarvestingForm.java --> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.main_settings_head">Localização do harvest da coleção</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.options_head">Opções de Harvesting</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_oai_provider">Provedor OAI</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_setid">Definir ID OAI</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_metadata_format">Formato de metadado</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaiurl">A url do repositório de destino do serviço de provedor OAI</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaiurl">Você deve fornecer um ID do conjunto da coleção de destino.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.help_oaisetid">O identificador persistente usado pelo provedor OAI para designar a coleção de destino</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.error_oaisetid">Você deve fornecer um ID do conjunto da coleção de destino.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Conteúdo sendo harvested</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.label_harvest_level">Conteúdo sendo harvested</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_only">Harvest só de metadado.</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_ref">Harvest de metadado e referência para bitstreams (requer suporte ORE).</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.option_md_and_bs">Harvest metadado e bitstreams (requer suporte ORE).</message> - <message key="xmlui.administrative.collection.SetupCollectionHarvestingForm.submit_test">Configurações de teste</message> - - <!-- org.dspace.app.xmlui.administrative.collection.EditCollectionHarvestingForm.java --> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.main_settings_head">Localização do Harvested da coleção</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_oai_provider">Provedor OAI</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_setid">Defina o ID OAI</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_metadata_format">Formato de metadado</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_level">Conteúdo do harvested</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_result">último resultado do Harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_result_new">Nesta coleção ainda não foi feito o harvested.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.label_harvest_status">Estado atual do harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_ready">Coleção pronta para o harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_busy">A coleção atual está no harvested</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_queued">A coleção está na fila para harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_oai_error">Erro OAI ocorreu durante o último harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.harvest_status_unknown_error">Ocorreu um erro inesperado durante o último harvest</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_only">Harvest só de metadados.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_ref">Harvest de metadado e referência para bitstreams.</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.option_md_and_bs">Harvest metadado e bitstreams (replicação completa).</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_change_settings">Alterar configurações</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_import_now">Importar agora</message> - <message key="xmlui.administrative.collection.EditCollectionHarvestingForm.submit_reimport_collection">Redefinir e reimportar a coleção</message> - - <message key="xmlui.administrative.ControlPanel.option_harvest">Harvesting</message> - <message key="xmlui.administrative.ControlPanel.harvest_scheduler_head">Harvest Scheduler Controls</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_status">Estado</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_actions">Ações</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_start">Começo do Harvester</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_reset">Redefinir o estado do Harvest</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_resume">Resumo</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_pause">Pausa</message> - <message key="xmlui.administrative.ControlPanel.harvest_submit_stop">Parada</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_collections">Configurações da coleção para o harvesting</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_active">Ativar harvests</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_queued">Queued harvests</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_errors">Erros do OAI</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_internal_errors">Erros internos</message> - <message key="xmlui.administrative.ControlPanel.harvest_head_generator_settings">Generator Settings</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_url">OAI-PMH URL</message> - <message key="xmlui.administrative.ControlPanel.harvest_label_oai_source">ORE source</message> - <message key="xmlui.administrative.ControlPanel.harvest_head_harvester_settings">Harvester Settings</message> - - <!-- General tags for community management --> - <message key="xmlui.administrative.community.general.community_trail">Comunidade</message> - <message key="xmlui.administrative.community.general.options_metadata">Edição de metadado</message> - <message key="xmlui.administrative.community.general.options_roles">Atribuir função</message> - <message key="xmlui.administrative.community.general.options_curate">Revisão</message> - <message key="xmlui.administrative.community.general.options_queue">Fila</message> - - <!-- org.dspace.app.xmlui.administrative.community.AssignCommunityRoles.java --> - <message key="xmlui.administrative.community.AssignCommunityRoles.title">Editar a função da comunidade</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.trail">Função</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.main_head">Editar comunidade: {0}</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.no_role">nenhuma</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.create">Criação...</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.help_admins">Comunidade de administradores pode criar subcomunidades ou coleções e gerenciar ou atribuir o gerenciamento para as subcomunidades ou coleções. Além disso, eles decidem quem pode enviar os itens para todas as sub-coleções, editar metadados dos item (após o envio) e adicionar (mapa) dos itens existentes de outras coleções (sujeitas a autorização).</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.default_read_custom">Esta comunidade usa as configurações personalizadas de acesso padrão. </message> - <message key="xmlui.administrative.community.AssignCommunityRoles.default_read_anonymous">O padrão de leitura para os itens de entrada e bitstreams estão configurados para Anônimo.</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.edit_authorizations">Edição das polÃticas de autorização.</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_name">Função</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_group">Grupo associado</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.role_buttons"> </message> - <message key="xmlui.administrative.community.AssignCommunityRoles.label_admins">Administradores</message> - <message key="xmlui.administrative.community.AssignCommunityRoles.sysadmins_only"><nobr>(sópara adminstradores do sistema)</nobr></message> - - <!-- org.dspace.app.xmlui.administrative.community.CurateCommunityForm.java --> - <message key="xmlui.administrative.community.CurateCommunityForm.main_head">Revisor da comunidade: {0}</message> - <message key="xmlui.administrative.community.CurateCommunityForm.title">Revisor da comunidade</message> - <message key="xmlui.administrative.community.CurateCommunityForm.trail">Revisor</message> - <message key="xmlui.administrative.community.CurateCommunityForm.label_name">Tarefa</message> - - <!-- org.dspace.app.xmlui.administrative.community.DeleteCommunityConfirm.java --> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.title">Confirmação de exclusão</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.trail">Confirmação</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.main_head">Confirmação de exclusão da comunidade {0}</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.main_para">Você tem certeza que a comunidade {0} deve ser excluÃda? Isto apagará:</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item1">Todas as coleções da comunidade que não estão inseridas em outras comunidades</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item2">Todos os itens e submissões incompletas desta comunidade que não estão inseridas em outras comunidades</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item3">O conteúdo destes itens</message> - <message key="xmlui.administrative.community.DeleteCommunityConfirm.confirm_item4">Todas as polÃticas de autorização associadas</message> - - <!-- org.dspace.app.xmlui.administrative.community.DeleteCommunityRoleConfirm.java --> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.title">Confirme a exclusão do documento</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.trail">Confirmação</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.main_head">Confirme a exclusão do documento {0}</message> - <message key="xmlui.administrative.community.DeleteCommunityRoleConfirm.main_para">Você tem certeza que quer excluir este documento? Todas as alterações e personalizações feitas ao grupo {0} serão perdidas e terão que ser criadas novamente.</message> - - <!-- org.dspace.app.xmlui.administrative.community.EditCommunityMetadataForm.java --> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.title">Edição de metadados da comunidade</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.trail">Metadado</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.main_head">Edição de metadado para a comunidade {0}</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.edit_authorizations">Edição de polÃticas de autorização</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_name">Nome</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_short_description">Pequena descrição</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_introductory_text">Texto introdutório (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_copyright_text">Texto sobre os direitos autorais (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_side_bar_text">NotÃcias (HTML)</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_logo">Upload de nova imagem</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.label_existing_logo">Imagem atual</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.submit_delete_logo">Excluir imagem</message> - <message key="xmlui.administrative.community.EditCommunityMetadataForm.submit_delete">Excluir comunidade</message> - - <!-- org.dspace.app.xmlui.administrative.community.CreateCommunityForm.java --> - <message key="xmlui.administrative.community.CreateCommunityForm.title">Criação de comunidade</message> - <message key="xmlui.administrative.community.CreateCommunityForm.trail">Criação de comunidade</message> - <message key="xmlui.administrative.community.CreateCommunityForm.main_head_sub">Informe os metadados para a nova subcomunidade {0}</message> - <message key="xmlui.administrative.community.CreateCommunityForm.main_head_top">Edite os metadados para o novo nÃvel acima da comunidade</message> - <message key="xmlui.administrative.community.CreateCommunityForm.submit_save">Criação</message> - - - <!-- org.dspace.app.xmlui.administrative.ControlPanel.java --> - <message key="xmlui.administrative.ControlPanel.title">Painel de controle</message> - <message key="xmlui.administrative.ControlPanel.trail">Painel de controle</message> - <message key="xmlui.administrative.ControlPanel.head">Painel de controle</message> - <message key="xmlui.administrative.ControlPanel.option_java">Informação Java</message> - <message key="xmlui.administrative.ControlPanel.option_dspace">Configuração da Biblioteca Digital</message> - <message key="xmlui.administrative.ControlPanel.option_alerts">Sistema de alerta</message> - <message key="xmlui.administrative.ControlPanel.hours">{0} h</message> - <message key="xmlui.administrative.ControlPanel.minutes">{0} m</message> - <message key="xmlui.administrative.ControlPanel.seconds">{0} s</message> - <message key="xmlui.administrative.ControlPanel.java_head">Java e operação do sistema</message> - <message key="xmlui.administrative.ControlPanel.java_version">Java Runtime Environment Version</message> - <message key="xmlui.administrative.ControlPanel.java_vendor">Java Runtime Environment Vendor</message> - <message key="xmlui.administrative.ControlPanel.os_name">Arquitetura do sistema operacional</message> - <message key="xmlui.administrative.ControlPanel.os_arch">Arquitetura do sistema operacional</message> - <message key="xmlui.administrative.ControlPanel.os_version">Arquitetura do sistema operacional</message> - <message key="xmlui.administrative.ControlPanel.runtime_head">Runtime estatÃsitcas</message> - <message key="xmlui.administrative.ControlPanel.runtime_processors">Avaliação do processo</message> - <message key="xmlui.administrative.ControlPanel.runtime_max">Memória máxima</message> - <message key="xmlui.administrative.ControlPanel.runtime_total">Memória alocada</message> - <message key="xmlui.administrative.ControlPanel.runtime_used">Memória usada</message> - <message key="xmlui.administrative.ControlPanel.runtime_free">Memória livre</message> - <message key="xmlui.administrative.ControlPanel.cocoon_head">Informação Cocoon</message> - <message key="xmlui.administrative.ControlPanel.cocoon_version">Versão Cocoon</message> - <message key="xmlui.administrative.ControlPanel.cocoon_cache_dir">Diretório oculto Cocoon</message> - <message key="xmlui.administrative.ControlPanel.cocoon_work_dir">Diretório de trabalho Cocoon</message> - <message key="xmlui.administrative.ControlPanel.cocoon_main_cache_size">Tamanho principal cache ({0})</message> - <message key="xmlui.administrative.ControlPanel.cocoon_cache_clear">(Limpar cache imediatamente)</message> - <message key="xmlui.administrative.ControlPanel.cocoon_persistent_cache_size">Tamanho cache persistente ({0})</message> - <message key="xmlui.administrative.ControlPanel.cocoon_transient_cache_size">Tamanho cache transitório ({0})</message> - <message key="xmlui.administrative.ControlPanel.dspace_head"> Ferramentas da Biblioteca Digital</message> - <message key="xmlui.administrative.ControlPanel.dspace_version">Versão do DSpace</message> - <message key="xmlui.administrative.ControlPanel.dspace_dir">Instalação do diretório DSpace</message> - <message key="xmlui.administrative.ControlPanel.dspace_url">URL base da Biblioteca Digital</message> - <message key="xmlui.administrative.ControlPanel.dspace_hostname">Nome hospedeiro da Biblioteca Digital</message> - <message key="xmlui.administrative.ControlPanel.dspace_name">Nome do site</message> - <message key="xmlui.administrative.ControlPanel.db_name"> Nome da base de dados</message> - <message key="xmlui.administrative.ControlPanel.db_url">URL da base de dados</message> - <message key="xmlui.administrative.ControlPanel.db_driver">JDBC Driver</message> - <message key="xmlui.administrative.ControlPanel.db_maxconnections">Número máximo de DB Connections in Pool</message> - <message key="xmlui.administrative.ControlPanel.db_maxwait">Tempo máximo de espera</message> - <message key="xmlui.administrative.ControlPanel.db_maxidle">Máximo de conecções ociosas</message> - <message key="xmlui.administrative.ControlPanel.mail_server">SMTP Servidor de correio</message> - <message key="xmlui.administrative.ControlPanel.mail_from_address">para o endereço de e-mail</message> - <message key="xmlui.administrative.ControlPanel.mail_feedback_recipient">Comentários do destinatário</message> - <message key="xmlui.administrative.ControlPanel.mail_admin">Administração geral da página e-mail</message> - <message key="xmlui.administrative.ControlPanel.alerts_head">Sistema de alerta</message> - <message key="xmlui.administrative.ControlPanel.alerts_warning"><strong>Aviso para o sistema de balanceamento de capacidade</strong>: Sistema de alerta são efetivos para o nóque é ativado. Você precisa garantir que cada nóno conjunto recebe o comando de alerta para ativação.</message> - <message key="xmlui.administrative.ControlPanel.alerts_message_label">Mensagem de alerta</message> - <message key="xmlui.administrative.ControlPanel.alerts_message_default">O sistema irá para a manutenção regular. Por favor, salve o seu trabalho e desconecte sua conta.</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_label">Contagem regressiva</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_none">Sem contagem regressiva</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_5">5 minutos</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_15">15 minutos</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_30">30 minutos</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_60">1 hora</message> - <message key="xmlui.administrative.ControlPanel.alerts_countdown_keep">Mantenha a contagem regressiva atual</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_label">Gerenciar sessão</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_all_sessions">Continuar para sessões autenticadas</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_current_sessions">Restringir a autenticação, mas manter as sessões atuais</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_only_administrative_sessions">Restringir a autenticação e excluir as sessões atuais</message> - <message key="xmlui.administrative.ControlPanel.alerts_session_note"><strong>Nota:</strong> Os administradores do site estão isentos de gerenciamento de sessão.</message> - <message key="xmlui.administrative.ControlPanel.alerts_submit_activate">Ativar</message> - <message key="xmlui.administrative.ControlPanel.alerts_submit_deactivate">Desativar</message> - <message key="xmlui.administrative.ControlPanel.activity_head">Atividade atual ({0} máximo de páginas)</message> - <message key="xmlui.administrative.ControlPanel.stop_anonymous">PARAR de registrar a atividade anônima.</message> - <message key="xmlui.administrative.ControlPanel.start_anonymous">COMEÇAR a registrar a atividade anônima.</message> - <message key="xmlui.administrative.ControlPanel.stop_bot">Interrompa a atividade de bot gravação.</message> - <message key="xmlui.administrative.ControlPanel.start_bot">Comece a atividade de bot gravação.</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_time">Tempo marcado</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_user">Usuário</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_ip">Endereço de IP</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_url">URL da página</message> - <message key="xmlui.administrative.ControlPanel.activity_sort_Agent">Usiário-agente</message> - <message key="xmlui.administrative.ControlPanel.activity_anonymous">Anônimo {0}</message> - <message key="xmlui.administrative.ControlPanel.activity_none">As páginas de visualização não foram registradas.</message> - - <message key="xmlui.administrative.ControlPanel.select_panel">Use as guias acima para selecionar as informações a seguir</message> - - <!-- org.dspace.app.xmlui.administrative.SystemwideAlerts --> - <message key="xmlui.administrative.SystemwideAlerts.countdown"><strong>Em {0} minutos</strong>: </message> - - <!-- org.dspace.app.xmlui.administrative.NotAuthorized --> - <message key="xmlui.administrative.NotAuthorized.title">Não autorizado</message> - <message key="xmlui.administrative.NotAuthorized.trail">Não autorizado</message> - <message key="xmlui.administrative.NotAuthorized.head">Privilégio insuficiente</message> - <message key="xmlui.administrative.NotAuthorized.para1a">Sua conta não tem privilégios suficientes para executar a ação solicitada. Se você acha que isso é um erro ou tem dúvidas sobre seus privilégios, por favor entre em contato com o administrador do sistema </message> - <message key="xmlui.administrative.NotAuthorized.para1b">administradores do sistema</message> - <message key="xmlui.administrative.NotAuthorized.para1c">.</message> - <message key="xmlui.administrative.NotAuthorized.para2">Entrar como outro usuário</message> - - <!-- Tarefas de curadoria de todo o sistema (org.dspace.app.xmlui.aspect.administrative.CurateForm) --> - <message key="xmlui.administrative.CurateForm.title">Tarefas de curadoria do sistema</message> - <message key="xmlui.administrative.CurateForm.trail">Tarefas de curadoria</message> - <message key="xmlui.administrative.CurateForm.object_label_name">Identificador de objetos da Biblioteca Digital</message> - <message key="xmlui.administrative.CurateForm.object_hint">Sugestão: Entre [seu-prefixo-identificador]/0 para executar uma tarefa dentro do site (nem todas as tarefas podem suportar esta capacidade)</message> - <message key="xmlui.administrative.CurateForm.task_label_name">Tarefa</message> - <!-- Usado por classes do formulário <DSO>--> - <message key="xmlui.administrative.CurateForm.taskgroup_label_name">Escolha entre os seguintes grupos</message> - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - Statistics Aspect - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - <message key="xmlui.statistics.title">EstatÃstica</message> - <message key="xmlui.statistics.search.title">EstatÃsticas de busca</message> - <message key="xmlui.statistics.search.head">EstatÃsticas de busca</message> - <message key="xmlui.statistics.search.head-dso">EstatÃstiacs de busca para {0}</message> - <message key="xmlui.statistics.search.error">Ocorreu um erro enquanto gerava a estatÃstica de busca, por favor, tento novamente mais tarde.</message> - <message key="xmlui.statistics.search.no-results">Nenhuma estatÃstica de busca está disponÃvel para o perÃodo selecionado.</message> - <message key="xmlui.statistics.workflow.title">EstatÃsticas de fluxo de submissão</message> - <message key="xmlui.statistics.visits.total">Total de visitas</message> - <message key="xmlui.statistics.visits.month">Total de visitas por mês</message> - <message key="xmlui.statistics.visits.views">Visualizações</message> - <message key="xmlui.statistics.visits.countries">Principais visualizações por paÃs</message> - <message key="xmlui.statistics.visits.cities">Principais visualizações por cidade</message> - <message key="xmlui.statistics.visits.bitstreams">Arquivos visitados</message> - <message key="xmlui.statistics.Navigation.title">EstatÃstica</message> - <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-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> - <message key="xmlui.statistics.workflow.error">Ocorreu um erro enquanto gerava a estatÃstica de busca, por favor, tento novamente mais tarde.</message> - <message key="xmlui.statistics.workflow.head">EstatÃsticas de fluxo de submissão</message> - <message key="xmlui.statistics.workflow.head-dso">EstatÃsticas de fluxo de submissão para {0}</message> - - - <message key="xmlui.statistics.StatisticsSearchTransformer.search-terms.head">Termos mais buscados</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.search-total.head">Total</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-month">Mês anterior</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-6-months">6 meses anteriores</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.last-year">Ano anterior</message> - <message key="xmlui.statistics.StatisticsSearchTransformer.time-filter.overall">Global</message> - - - <message key="xmlui.statistics.display.table.column-label.search-terms">termo para busca</message> - <message key="xmlui.statistics.display.table.column-label.searches">Buscas</message> - <message key="xmlui.statistics.display.table.column-label.percent-total">% of Total</message> - <message key="xmlui.statistics.display.table.column-label.views-search">Páginas vista / busca</message> - <message key="xmlui.statistics.display.table.column-label.step">Etapa</message> - <message key="xmlui.statistics.display.table.column-label.performed">Executado</message> - <message key="xmlui.statistics.display.table.column-label.average">Total</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP1POOL">Conjunto de etapas aceitas/Rejeitadas</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP1">Etapas aceitas/Rejeitadas</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP2POOL">Conjunto de metadados de etapas aceitas/rejeitadas/editadas</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP2">Metadados de etapas aceitas/rejeitadas/editadas</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP3POOL">Conjunto de metados de etapas</message> - <message key="xmlui.statistics.display.table.workflow.step.STEP3">Editar metadados de etapas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.reviewstep.claimaction">conjunto de etapas aceitas/rejeitadas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.reviewstep.reviewaction">etapas aceitas/rejeitadas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.editstep.claimaction">Conjunto de etapas aceitas/rejeitadas/editadas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.editstep.editaction">Metadados de etapas aceitas/rejeitadas/editadas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.finaleditstep.claimaction">Editar conjunto de metadados de etapas</message> - <message key="xmlui.statistics.display.table.workflow.step.default.finaleditstep.finaleditaction">Editar metadados de etapas </message> - - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.scoreReviewStep.claimaction">Conjunto de revisão de classificação</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.scoreReviewStep.scorereviewaction">Revisão de classificação</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.evaluationStep.evaluationaction">Avaliação de revisão de classificação</message> - <message key="xmlui.statistics.display.table.workflow.step.scoreReview.evaluationStep.noUserSelectionAction">Configuração de avaliação de revisão de classificação</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.selectReviewerStep.claimaction">Conjunto de revisão de um único usuário</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.singleUserReviewStep.autoassignAction">Atribuir ação para um usuário único</message> - <message key="xmlui.statistics.display.table.workflow.step.selectSingleReviewer.singleUserReviewStep.singleuserreviewaction">revisão de um único usuário</message> - - - - - - - - - <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - dri2xhtml - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!--> - - - - - - <!-- structural.xsl --> - <message key="xmlui.dri2xhtml.structural.footer-promotional"> - <a href="http://di.tamu.edu" id="ds-logo-link"> - <span id="ds-footer-logo"></span> - </a> - <p> - Este site está usando Manakin, uma nova versão para o DSpace criado por Texas AeM University - Libraries. A interface pode ser consideravelmente modificada por meio de Manakin Aspects e XSL baseado em Themes. - Para mais informações visite - <a href="http://di.tamu.edu">http://di.tamu.edu</a> e - <a href="http://dspace.org">http://dspace.org</a> - </p> - </message> - <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.profile">Perfil: </message> - <message key="xmlui.dri2xhtml.structural.logout">Sair</message> - <message key="xmlui.dri2xhtml.structural.login">Entrar</message> - - <message key="xmlui.dri2xhtml.structural.search">Buscar na Biblioteca Digital</message> - <message key="xmlui.dri2xhtml.structural.search-advanced">Busca avançada</message> - <message key="xmlui.dri2xhtml.structural.search-in-community">Esta comunidade</message> - <message key="xmlui.dri2xhtml.structural.search-in-collection">Esta coleção</message> - - <message key="xmlui.dri2xhtml.structural.pagination-previous">Página anterior</message> - <message key="xmlui.dri2xhtml.structural.pagination-info">Itens para a visualização no momento {0}-{1} of {2}</message> - <message key="xmlui.dri2xhtml.structural.pagination-next">Próxima página</message> - - <message key="xmlui.dri2xhtml.structural.link_cc">Creative Commons</message> - <message key="xmlui.dri2xhtml.structural.link_original_license">Licença original</message> - - - <!-- DS-METS-1.0-MODS.xsl --> - <!-- DS-METS-1.0-DIM.xsl --> - <!-- DS-METS-1.0-QDC.xsl --> - <message key="xmlui.dri2xhtml.METS-1.0.no-preview">Visualização não disponÃvel</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-title">Sem tÃtulo</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-author">Autor desconhecido</message> - <message key="xmlui.dri2xhtml.METS-1.0.non-conformant"> - Este não é um objeto formatado para o perfil METS 1.0 do DSpace e portanto não pode ser - utilizado de forma eficaz. Você pode substituir o modelo que lida com o caso dri2xhtml - para execultar a função necessária, ou criar o seu modelo para combinar com o perfil que você utiliza. - </message> - - <message key="xmlui.dri2xhtml.METS-1.0.item-preview">Visualização</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-title">TÃtulo</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-author">Autor</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-abstract">Resumo</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-description">Descrição</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-uri">URI</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-date">Data</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-publisher">Editor</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-subject">Assunto</message> - - <message key="xmlui.dri2xhtml.METS-1.0.item-files-head">Arquivos deste item</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-file">Arquivos</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-name">Nome</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-size">Tamanho</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-format">Formato</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-view">Visualização</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-description">Descrição</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-files-viewOpen">Visualizar/<wbr/>Abrir</message> - <message key="xmlui.dri2xhtml.METS-1.0.item-no-files">Não existem arquivos associados a este item.</message> - - <message key="xmlui.dri2xhtml.METS-1.0.size-bytes">bytes</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-kilobytes">Kb</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-megabytes">Mb</message> - <message key="xmlui.dri2xhtml.METS-1.0.size-gigabytes">Gb</message> - - <message key="xmlui.dri2xhtml.METS-1.0.license-text">Os arquivos de licença a seguir estão associados a este item:</message> - <message key="xmlui.dri2xhtml.METS-1.0.cc-license-text">Exceto quando indicado o contrário, a licença deste item é descrito como </message> - - <message key="xmlui.dri2xhtml.METS-1.0.collection-not-implemented"> - O sumário de visualização de uma coleção não é utilizada atualmente ou implementada. Isto pode ser fixado - substituindo o modelo dri2xhtml's modelo chamado collectionSummaryView - </message> - <message key="xmlui.dri2xhtml.METS-1.0.community-not-implemented"> - O sumário de visualização de uma comunidade não é utilizada atualmente ou implementada. Isto pode ser fixado - substituindo o modelo dri2xhtml's modelo chamado communitySummaryView. - </message> - - <message key="xmlui.dri2xhtml.METS-1.0.collection-logo-alt">A imagem da coleção</message> - <message key="xmlui.dri2xhtml.METS-1.0.community-logo-alt">A imagem da comunidade</message> - <message key="xmlui.dri2xhtml.METS-1.0.no-logo-alt">Sem imagem</message> - <message key="xmlui.dri2xhtml.METS-1.0.news">NotÃcias</message> - - <!-- Elementos especÃficos para a internacionalização do qualificador de metadado Dublin Core. - DS-METS-1.0-QDC.xsl --> - <message key="xmlui.dri2xhtml.METS-1.0.qdc-not-applicable"> - Qualificador Dublin Core (QDC) não é aplicável agora para as comunidades e coleções da Biblioteca Digital. - Quando utilizar QDC, você deve utilizar a versão QDC crosswalk para itens DSpace e/ou - DIM ou MODS para o processamento de comunidades e coleções. - </message> - - <message key="xmlui.dri2xhtml.METS-1.0.header-qdc-elements">Elementos Dublin Core</message> - <message key="xmlui.dri2xhtml.METS-1.0.header-qdc-terms">Termos Dublin Core</message> - - - <!-- Primeiro texto modelo especial que indica onde o texto deve acabar --> - <message key="xmlui.dri2xhtml.pioneer.preview">Visualização</message> - <message key="xmlui.dri2xhtml.pioneer.date">Data</message> - <message key="xmlui.dri2xhtml.pioneer.title">Titulo</message> - <message key="xmlui.dri2xhtml.pioneer.author">Autor</message> - - <!-- tag usada para manipular the o texto da área vazia e adicionar tag 09/28/2006 --> - <message key="xmlui.dri2xhtml.default.textarea.value"> </message> - - <!--###### File Format MIME Type Mappings ######--> - - <!-- Application-based formats --> - <message key="xmlui.dri2xhtml.mimetype.application/marc">Registro MARC</message> - <message key="xmlui.dri2xhtml.mimetype.application/mathematica">Matemática</message> - <message key="xmlui.dri2xhtml.mimetype.application/msword">Microsoft Word</message> - <message key="xmlui.dri2xhtml.mimetype.application/octet-stream">Desconhecido</message> - <message key="xmlui.dri2xhtml.mimetype.application/pdf">PDF</message> - <message key="xmlui.dri2xhtml.mimetype.application/postscript">Postscript</message> - <message key="xmlui.dri2xhtml.mimetype.application/sgml">SGML</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-excel">Microsoft Excel</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-powerpoint">Microsoft PowerPoint</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.ms-project">Microsoft Project</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.database">OpenOffice Base</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.formula">OpenOffice Math</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.graphics">OpenOffice Draw</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.presentation">OpenOffice Impress</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.spreadsheet">OpenOffice Calc</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.oasis.opendocument.text">OpenOffice Writer</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.presentationml.presentation">Microsoft PowerPoint 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.spreadsheetml.sheet">Microsoft Excel 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.openxmlformats-officedocument.wordprocessingml.document">Microsoft Word 2007</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.calc">OpenOffice Calc (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.draw">OpenOffice Draw (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.impress">OpenOffice Impress (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.sun.xml.writer.global">OpenOffice Writer (1.x)</message> - <message key="xmlui.dri2xhtml.mimetype.application/vnd.visio">Microsoft Visio</message> - <message key="xmlui.dri2xhtml.mimetype.application/wordperfect5.1">WordPerfect</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-dvi">TeX DVI</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-filemaker">FileMaker Pro</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-java-applet">Java applet</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-latex">LaTeX</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-photoshop">Photoshop</message> - <message key="xmlui.dri2xhtml.mimetype.application/x-tex">TeX</message> - - <!-- AFormatos baseados em áudio --> - <message key="xmlui.dri2xhtml.mimetype.audio/basic">Basic Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/flac">FLAC Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/m4a">AAC audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/m4a-latm">AAC audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/mpeg">mp3 audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-aiff">AIFF audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-mpeg">MPEG Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ms-wma">WMA Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ms-wmv">WMV Audio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-ogg">Ogg Vorbis</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-pn-realaudio">RealAudio</message> - <message key="xmlui.dri2xhtml.mimetype.audio/x-wav">WAV audio</message> - - <!-- Image-based formats --> - <message key="xmlui.dri2xhtml.mimetype.image/gif">GIF image</message> - <message key="xmlui.dri2xhtml.mimetype.image/jp2">JPEG 2000 image</message> - <message key="xmlui.dri2xhtml.mimetype.image/jpeg">JPEG image</message> - <message key="xmlui.dri2xhtml.mimetype.image/png">PNG image</message> - <message key="xmlui.dri2xhtml.mimetype.image/tiff">TIFF image</message> - <message key="xmlui.dri2xhtml.mimetype.image/x-ms-bmp">BMP image</message> - <message key="xmlui.dri2xhtml.mimetype.image/x-photo-cd">Photo CD</message> - - <!-- Formatos baseados em texto --> - <message key="xmlui.dri2xhtml.mimetype.text/css">CSS file</message> - <message key="xmlui.dri2xhtml.mimetype.text/csv">CSV file</message> - <message key="xmlui.dri2xhtml.mimetype.text/html">HTML</message> - <message key="xmlui.dri2xhtml.mimetype.text/javascript">Javascript</message> - <message key="xmlui.dri2xhtml.mimetype.text/plain">Text file</message> - <message key="xmlui.dri2xhtml.mimetype.text/richtext">RTF file</message> - <message key="xmlui.dri2xhtml.mimetype.text/xml">XML</message> - - <!-- Video-based formats --> - <message key="xmlui.dri2xhtml.mimetype.video/avi">AVI video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mjp2">Motion JPEG 2000</message> - <message key="xmlui.dri2xhtml.mimetype.video/mpeg">MPEG video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mpeg2">MPEG-2 video</message> - <message key="xmlui.dri2xhtml.mimetype.video/mp4">MPEG-4 video</message> - <message key="xmlui.dri2xhtml.mimetype.video/quicktime">QuickTime video</message> - - <!-- mensagens explicativas para a escloha dos valores confiáveis de autoridade --> - <message key="xmlui.authority.confidence.description.cf_unset">Os valores confiáveis nunca foram gravados</message> - <message key="xmlui.authority.confidence.description.cf_novalue">Nenhum valor razoável de confiança foi desenvolvido para autoridade</message> - <message key="xmlui.authority.confidence.description.cf_rejected">Recomenda-se que esta submissão seja rejeitada</message> - <message key="xmlui.authority.confidence.description.cf_failed">Foi encontrada uma falha interna</message> - <message key="xmlui.authority.confidence.description.cf_notfound">Não há respostas correspondentes</message> - <message key="xmlui.authority.confidence.description.cf_ambiguous">Existem vários valores de autoridade correspondentes de igual validade</message> - <message key="xmlui.authority.confidence.description.cf_uncertain">o valor é singular e válido, mas nã foi visto e aceito, por isso ainda é incerto</message> - <message key="xmlui.authority.confidence.description.cf_accepted">Este valor precisa ser confirmado por um usuário interativo</message> - <!-- mensagem de ajuda em "unlock" no butão Edição de metadado --> - <message key="xmlui.authority.confidence.unlock.help">Desative a chave do valor de autoridade para a edição manual ou mantenha bloqueada </message> - - <!-- Opção de busca na janela popup --> - <!-- NOTA: Estas mensagens necessariamente usam um formato diferente para - - parâmetros, infelizmente, desde a substituição ocorre no - - JavaScript (AJAX) que completa a busca na janela popup. - - Então, a posição dos parâmetros são @1@, @2@, etc. - --> - <message key="xmlui.ChoiceLookupTransformer.title">Valor de busca Biblioteca Digital</message> - <message key="xmlui.ChoiceLookupTransformer.accept">Aceito</message> - <message key="xmlui.ChoiceLookupTransformer.add">Adicionar</message> - <message key="xmlui.ChoiceLookupTransformer.cancel">Cancelar</message> - <message key="xmlui.ChoiceLookupTransformer.more">Veja mais resultados</message> - <!-- params são: inÃcio, fim, total de contas, valor da busca --> - <message key="xmlui.ChoiceLookupTransformer.results">Resultados @1@ a @2@ de @3@ para "@4@"</message> - <message key="xmlui.ChoiceLookupTransformer.fail">Falha ao carregar os dados selecionados: </message> - - <!-- Escolha para a pesquisa - exemplo de configuração para o campo dc.publisher --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.help">Nome do editor</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.title">Buscar editor</message> - <!-- Params são: valor da busca --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_publisher.nonauthority">Valor de não-autoridade: @1@</message> - - <!-- Escolha para a pesquisa - exemplo de configuração o campo para dc.contributor.author --> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help">O nome deve ser informado como "último, Primeiro" </message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help.last">Útimo nome, ex. "Silva"</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.help.first">Primeiro nome(s) ex. "João"</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.title">Nome do autor para pesquisa</message> - <message key="xmlui.ChoiceLookupTransformer.field.dc_contributor_author.nonauthority">Local value "@1@" (não é para nomeação de autoridade)</message> - - <!-- mobile theme --> - <message key="xmlui.mobile.home_mobile">Biblioteca Digital para dispositÃvos móveis</message> - <message key="xmlui.mobile.search_all">Buscar em tudo</message> - <message key="xmlui.mobile.browse_all">navegar em tudo por</message> - <message key="xmlui.mobile.browse_date">Data</message> - <message key="xmlui.mobile.browse_author">Autor</message> - <message key="xmlui.mobile.browse_title">TÃtulo</message> - <message key="xmlui.mobile.browse_subject">Assunto</message> - <message key="xmlui.mobile.related_google_scholar">Relacionado</message> - <message key="xmlui.mobile.items_in_google_scholar">Itens no Google acadêmico</message> - <message key="xmlui.mobile.download">Baixar</message> - - - <!-- Versioning --> - <message key="xmlui.aspect.versioning.VersioningNavigation.context_create_version">Criar versão deste item</message> - <message key="xmlui.aspect.versioning.VersioningNavigation.context_show_version_history">Apresentar histórico de versionamento</message> - - <message key="xmlui.aspect.versioning.VersionItemForm.title">Criar versão</message> - <message key="xmlui.aspect.versioning.VersionItemForm.trail">Versão</message> - <message key="xmlui.aspect.versioning.VersionItemForm.head1">Criar nova versão do item: {0}</message> - <message key="xmlui.aspect.versioning.VersionItemForm.submit_version">Versão</message> - <message key="xmlui.aspect.versioning.VersionItemForm.submit_update_version">Alterar versão</message> - <message key="xmlui.aspect.versioning.VersionItemForm.summary">Razão para criar nova versão</message> - - <message key="xmlui.aspect.versioning.VersionUpdateForm.title">Alterar versão</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.trail">Versão</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.head1">Alterar versão do item: {0}</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.submit_version">Versão</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.submit_update_version">Alterar versão</message> - <message key="xmlui.aspect.versioning.VersionUpdateForm.summary">Sumário</message> - - - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.title">Confirmar exclusão</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.trail">Confirmar exclusão</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.head1">Confirmar exclusão(ões)</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.para1">Tem certeza que deseja remover estas versões? </message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.para2">IMPORTANTE: deletando estas versões, os itens associados não estarão mais acessÃveis.</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column1">Versão</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column2">Item</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column3">Editor</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column4">Data</message> - <message key="xmlui.aspect.versioning.DeleteVersionsConfirm.column5">Sumário</message> - - - <message key="xmlui.aspect.versioning.RestoreVersionForm.title">Recuperar versão</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.trail">Recuperar versão</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.head1">Recuperar versão</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.para1">Tem certeza que deseja recuperar esta versão?</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column1">Versão</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column2">Editor</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column3">Data</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.column4">Sumário</message> - <message key="xmlui.aspect.versioning.RestoreVersionForm.restore">Recuperar</message> - - <message key="xmlui.aspect.versioning.VersionHistoryForm.head2">Histórico de versionamento</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column1">Versão</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column2">Item</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column3">Editor</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column4">Data</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column5">Sumário</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.column6">Ações</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.restore">Recuperar</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.update">Alterar</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.legend">*Selecionar versão</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.delete">Deletar versões</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.return">Voltar</message> - <message key="xmlui.aspect.versioning.VersionHistoryForm.collection_admins_only">(Somente coleções do administrador)</message> - - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.new_version_head">Notificar</message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.new_version_help">Esta não é a última versão do item. A versão mais nova pode ser encontrada em: </message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.workflow_version_head">Notificar</message> - <message key="xmlui.aspect.versioning.VersionNoticeTransformer.notice.workflow_version_help">Uma versão mais recente deste item está em processo de submissão.</message> - - <!-- End Versioning --> - - - <!-- Discovery --> - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dc.contributor.author_filter">Autor</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dc.subject_filter">Assunto</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dc.type_filter">Tipo de conteúdo</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dc.date.issued">Data de publicação</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dateIssued">Data de publicação</message> - - - <!-- Site Leve Recently Added Content --> - <message key="xmlui.ArtifactBrowser.SiteViewer.head_recent_submissions">Submissões recentes</message> - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_type_filter">Tipo</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_publisher_filter">Editora</message> - - - <message key="xmlui.ArtifactBrowser.AbstractSearch.sort_by.ispartof">Relação</message> - - <message key="xmlui.ArtifactBrowser.AbstractSearch.group_by">Resultados agrupados por</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.group_by.none">Nenhum</message> - - - <message key="xmlui.ArtifactBrowser.AbstractSearch.group_by.publication_grp">Publicação</message> - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_location.comm">Comunidade</message> - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_location.coll">Coleção</message> - - - <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_dc.relation.ispartofseries_filter">Séries</message> - - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_dc.contributor.author_browse">Navegar por: Autor</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_dc.title_browse">Navegar por: TÃtulo</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_dc.subject_browse">Navegar por: Assunto</message> - - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_dc.description.abstract_browse">Navegar por: Resumo</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_series_browse">Navegar por: Séries</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_sponsor_browse">Navegar por: Patrocinador</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_identifier_browse">Navegar por: Identificador</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_language_browse">Navegar por: Idioma (ISO)</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_keyword_browse">Navegar por: Palavra-chave</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_taxon_browse">Navegar por: Nome cientÃfico</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_contributor_browse">Navegar por: Contribuidor</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_creator_browse">Navegar por: Autor</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_subject_browse">Navegar por: Assunto</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_description_browse">Navegar por: Descrição</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_relation_browse">Navegar por: Relação</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_mime_browse">Navegar por: Mime-Type</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_other_browse">Navegar por: Outros contribuidores</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_advisor_browse">Navegar por: Orientador</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_department_browse">Navegar por: Departamento</message> - <message key="xmlui.ArtifactBrowser.AbstractSearch.type_dateissued_dt_browse">Navegar por: Data de publicação</message> - - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.author">Autor</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.title">TÃtulo</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.subject">Assunto</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.dateIssued">Data de publicação</message> - - - - <message key="xmlui.dri2xhtml.structural.pagination-info.nototal">Agora, apresentando os itens {0}-{1}</message> - - <message key="xmlui.Discovery.AbstractSearch.type_author">Filtrador por: Autor</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.author">Autor</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.author_filter">Autor</message> - <message key="xmlui.Discovery.AbstractSearch.type_subject">Filtrador por: Assunto</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.subject">Assunto</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.subject_filter">Assunto</message> - <message key="xmlui.ArtifactBrowser.SimpleSearch.filter.dateIssued.year">Data de publicação</message> - - - <message key="xmlui.Discovery.AbstractSearch.startswith">Iniciar com</message> - <message key="xmlui.Discovery.AbstractSearch.startswith.help">Ou entre com as primeiras letras:</message> - - <message key="xmlui.Discovery.AbstractSearch.sort_by.head">Opção de ordenação:</message> - <message key="xmlui.Discovery.AbstractSearch.sort_by.relevance">Relevância</message> - <message key="xmlui.Discovery.AbstractSearch.sort_by.dc.title_sort_desc">TÃtulo - decrescente</message> - <message key="xmlui.Discovery.AbstractSearch.sort_by.dc.date.issued_dt_desc">Data de publicação - decrescente</message> - - <message key="xmlui.Discovery.AbstractSearch.sort_by.dc.title_sort_asc">TÃtulo - crescente</message> - <message key="xmlui.Discovery.AbstractSearch.sort_by.dc.date.issued_dt_asc">Data de publicação - crescente</message> - - <message key="xmlui.Discovery.AbstractSearch.rpp">Resultados por página:</message> - - - <message key="xmlui.Discovery.AbstractSearch.filters.controls.add-filter">Adicionar filtro</message> - <message key="xmlui.Discovery.AbstractSearch.filters.controls.apply-filters">Aplicar</message> - <message key="xmlui.Discovery.AbstractSearch.filters.controls.remove-filter">Remover</message> - <message key="xmlui.Discovery.AbstractSearch.filters.controls.new-filters.head">Novo Filtro:</message> - <message key="xmlui.Discovery.AbstractSearch.filters.controls.current-filters.head">Filtros correntes:</message> - <message key="xmlui.Discovery.AbstractSearch.filters.display">Adicionar filtros</message> - - <message key="xmlui.discovery.SearchFacetFilter.no-results">Nenhum valor para o filtro encontrado</message> - - <message key="xmlui.discovery.AbstractFiltersTransformer.filters.head">Discover</message> - <message key="xmlui.discovery.AbstractFiltersTransformer.filters.view-more">... Ver mais</message> - - - <message key="xmlui.Discovery.SimpleSearch.search_scope">Buscar</message> - <message key="xmlui.discovery.SimpleSearch.search_label">Buscar</message> - <message key="xmlui.Discovery.SimpleSearch.filter_head">Filtros</message> - <message key="xmlui.Discovery.SimpleSearch.filter_help">Utilize filtros para refinar o resultado de busca.</message> - - <message key="xmlui.Discovery.SimpleSearch.filter.contains">Contém</message> - <message key="xmlui.Discovery.SimpleSearch.filter.equals">Igual</message> - <message key="xmlui.Discovery.SimpleSearch.filter.authority">ID</message> - <message key="xmlui.Discovery.SimpleSearch.filter.notcontains">Não contém</message> - <message key="xmlui.Discovery.SimpleSearch.filter.notequals">Diferentes</message> - <message key="xmlui.Discovery.SimpleSearch.filter.notauthority">sem ID</message> - - <message key="xmlui.Discovery.RelatedItems.head">Itens relacionados</message> - <message key="xmlui.Discovery.RelatedItems.help">Apresentado os itens relacionados pelo tÃtulo, autor e assunto.</message> - - <message key="xmlui.Discovery.AbstractSearch.head1_community">Apresentado {0} de um total de {1} resultados para a comunidade: {2}. <span class="searchTime">({3} seconds)</span></message> - <message key="xmlui.Discovery.AbstractSearch.head1_collection">Apresentando {0} de um total de {1} resultados para a coleção: {2}. <span class="searchTime">({3} seconds)</span></message> - <message key="xmlui.Discovery.AbstractSearch.head1_none">Apresentando {0} de um total de {1} resultados. <span class="searchTime">({2} seconds)</span></message> - - <message key="xmlui.Discovery.AbstractSearch.head2">Comunidades ou coleções que correspondem a requisição</message> - <message key="xmlui.Discovery.AbstractSearch.head3">Itens que correspondem a requisição</message> - - - <!-- SwordClient --> - - <message key="xmlui.swordclient.Navigation.context_head">Copiar pelo protocolo SWORD</message> - <message key="xmlui.swordclient.Navigation.context_copy">Copiar item para outro repositório</message> - <message key="xmlui.swordclient.general.SwordCopy_trail">Copiar pelo protocolo SWORD</message> - <message key="xmlui.swordclient.general.main_head">Copoiar item: {0}</message> - - - <message key="xmlui.swordclient.SelectTarget.title">Destino da cópia SWORD</message> - <message key="xmlui.swordclient.SelectTarget.trail">Selecionar destino</message> - <message key="xmlui.swordclient.SelectTarget.url">URL</message> - <message key="xmlui.swordclient.SelectTarget.other_url">URL alternativa</message> - <message key="xmlui.swordclient.SelectTarget.username">Identificação</message> - <message key="xmlui.swordclient.SelectTarget.password">Senha</message> - <message key="xmlui.swordclient.SelectTarget.on_behalf_of">Em nome de</message> - - <message key="xmlui.swordclient.SelectTargetAction.url_error">URL inválida</message> - <message key="xmlui.swordclient.SelectTargetAction.username_error">Identificação inválida</message> - <message key="xmlui.swordclient.SelectTargetAction.password_error">Senha inválida</message> - <message key="xmlui.swordclient.SelectTargetAction.serviceDoc_error">Erro buscando documento SWORD: {0}</message> - - <message key="xmlui.swordclient.SelectCollection.title">Coleção destino para o SWORD</message> - <message key="xmlui.swordclient.SelectCollection.trail">Selecionar coleção</message> - <message key="xmlui.swordclient.SelectCollection.collection_head">Coleção: {0}</message> - <message key="xmlui.swordclient.SelectCollection.collection_title">TÃtulo: {0} </message> - <message key="xmlui.swordclient.SelectCollection.collection policy">PolÃtica: {0}</message> - <message key="xmlui.swordclient.SelectCollection.collection_mediation">Mediação: {0}</message> - <message key="xmlui.swordclient.SelectCollection.collection_file_types">Tipos de arquivos: {0}</message> - <message key="xmlui.swordclient.SelectCollection.collection_package_formats">Formato de pacote: {0}</message> - <message key="xmlui.swordclient.SelectCollection.collection_deposit_button">Depositar nesta localização</message> - - <message key="xmlui.swordclient.SelectCollection.sub_service_target">Destuno do sub-serviço</message> - <message key="xmlui.swordclient.SelectCollection.sub_service_target_button">Obter documento de sub-serviço</message> - - <message key="xmlui.swordclient.SelectPackagingAction.head">Coleção:{0}</message> - <message key="xmlui.swordclient.SelectPackagingAction.title">TÃtulo: {0}</message> - <message key="xmlui.swordclient.SelectPackagingAction.policy">PolÃtica: {0} </message> - <message key="xmlui.swordclient.SelectPackagingAction.mediation">Mediação:{0} </message> - <message key="xmlui.swordclient.SelectPackagingAction.file_types">Tipos de arquivos</message> - <message key="xmlui.swordclient.SelectPackagingAction.package_formats">Formato de pacote</message> - <message key="xmlui.swordclient.SelectPackagingAction.packageFormat_error">Formato de pacote selecionado nao suportado</message> - - <message key="xmlui.swordclient.DepositAction.success">Cópia do item realizada com sucesso</message> - <message key="xmlui.swordclient.DepositAction.package_error">Erro no formato do pacote</message> - <message key="xmlui.swordclient.DepositAction.invalid_handle">Indentificador persistente inválido</message> - <message key="xmlui.swordclient.DepositAction.package_error">Um erro ocorreu na criação do pacote do objeto</message> - <message key="xmlui.swordclient.DepositAction.error">Erro encontrado durate o processo de depósito: {0}</message> - - <message key="xmlui.swordclient.SwordResponse.title">Resultado SWORD</message> - <message key="xmlui.swordclient.SwordResponse.trail">Resultado SWORD</message> - - - <!-- XMLWorkflow --> - - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.info1">Ações que podem ser executadas nesta tarefa:</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.take_help">Assumir esta tarefa.</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.take_submit">Pegar tarefa</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.leave_help">Deixar a tarefa para outro pegar.</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.leave_submit">Deixar tarefa</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.back">Retornar à visão geral</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.title">Aceitar/Rejeitar tarefa</message> - - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.head">Executar tarefa: Aceitar/Rejeitar item</message> - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.info1">Ações que podem ser executadas nesta tarefa:</message> - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.reject_help">Caso tenha avaliado o item e concluÃdo como <strong>não</strong> indicado para inclusão na coleção, selecione "Rejeitar". Será pedido que entre com uma mensagem, indicando a razão da rejeição e se é possÃvel ressubmeter o item com alterações.</message> - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.reject_submit">Rejeitar item</message> - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.approve_help">Caso tenha avaliado o item e concluÃdo pela inclusão na coleção, selecione "Aprovar".</message> - <message key="xmlui.XMLWorkflow.workflow.AcceptAction.approve_submit">Aprovar item</message> - - - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.head">Executar tarefa: Aceitar/Rejeitar/Editar item</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.info1">Ações que podem ser executadas nesta tarefa:</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.reject_help">Caso tenha avaliado o item e concluÃdo como <strong>não</strong> indicado para inclusão na coleção, selecione "Rejeitar". Será pedido que entre com uma mensagem, indicando a razão da rejeição e se é possÃvel ressubmeter o item com alterações.</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.reject_submit">Rejeitar item</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.approve_help">Caso tenha avaliado o item e concluÃdo pela inclusão na coleção, selecione "Aprovar".</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.approve_submit">Rejeitar item</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.edit_help">Selecione esta opção para alterar os metadados do item.</message> - <message key="xmlui.XMLWorkflow.workflow.EditMetadataAction.edit_submit">Editar metadado</message> - - <message key="xmlui.XMLWorkflow.step.unknown">Estado desconhecido</message> - - <message key="xmlui.XMLWorkflow.workflow.SelectReviewerAction.head">Executar tarefa: atribuir avaliador</message> - <message key="xmlui.XMLWorkflow.workflow.SelectReviewerAction.help">Utilize a caixa abaixo para buscar por um usuário a ser indicador como revisor da tarefa.</message> - <message key="xmlui.XMLWorkflow.workflow.SelectReviewerAction.search.label">Buscar por avaliador</message> - <message key="xmlui.XMLWorkflow.workflow.SelectReviewerAction.search.button">Buscar por usuário</message> - <message key="xmlui.XMLWorkflow.workflow.SelectReviewerAction.select-reviewer.button">Selecionar como avaliador</message> - - <message key="xmlui.XMLWorkflow.workflow.SingleUserReviewAction.decline.help">Caso não seja a pessoa apropriada para avaliar o item, pode-se declinar da tarefa, selecionado o botão de "Declinar tarefa" .</message> - <message key="xmlui.XMLWorkflow.workflow.SingleUserReviewAction.decline.button">Declinar tarefa</message> - - - <message key="xmlui.XMLWorkflow.workflow.ScoreReviewAction.head">Avaliar submissão</message> - <message key="xmlui.XMLWorkflow.workflow.ScoreReviewAction.score.button">Avaliar submissão</message> - <message key="xmlui.XMLWorkflow.workflow.ScoreReviewAction.help">Entre com a pontuação para esta submissão</message> - - - <message key="xmlui.XMLWorkflow.Navigation.xmlworkflow_overview">Visão geral do fluxo de trabalho</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.trail">Visão geral do fluxo de trabalho</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.title">Visão geral do fluxo de trabalho</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.search_column1"> </message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.search_column2">Passo</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.search_column3">Item</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.search_column4">Coleção</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.search_column5">Depositante</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.button.submit_submitter">Enviar itens de volta ao depositante</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.button.submit_delete">Deletar itens</message> - <message key="xmlui.XMLWorkflow.WorkflowOverviewTransformer.button.no_results">Sem resultados</message> - - - <message key="xmlui.XMLWorkflow.WorkflowItemTransformer.title">Apresentar item no fluxo de trabalho: {0}</message> - <message key="xmlui.XMLWorkflow.WorkflowItemTransformer.trail">Apresentar item no fluxo de trabalho</message> - - <message key="xmlui.XMLWorkflow.default.reviewstep">Aceitar/Rejeitar</message> - <message key="xmlui.XMLWorkflow.default.reviewstep.claimaction">Aceitar/Rejeitar</message> - <message key="xmlui.XMLWorkflow.default.reviewstep.reviewaction">Aceitar/Rejeitar</message> - - <message key="xmlui.XMLWorkflow.default.editstep">Aceitar/Rejeitar/Editar passo</message> - <message key="xmlui.XMLWorkflow.default.editstep.claimaction">Aceitar/Rejeitar/Editar</message> - <message key="xmlui.XMLWorkflow.default.editstep.editaction">Aceitar/Rejeitar/Editar</message> - - <message key="xmlui.XMLWorkflow.default.finaleditstep">Aceitar/Editar passo final</message> - <message key="xmlui.XMLWorkflow.default.finaleditstep.claimaction">Aceitar/Editar passo final</message> - <message key="xmlui.XMLWorkflow.default.finaleditstep.finaleditaction">Aceitar/Editar passo final</message> - - - <message key="xmlui.XMLWorkflow.selectSingleReviewer.selectReviewerStep.claimaction">Passo de atribuir avaliador</message> - <message key="xmlui.XMLWorkflow.selectSingleReviewer.selectReviewerStep.selectrevieweraction">Atribuir avaliador</message> - - <message key="xmlui.XMLWorkflow.selectSingleReviewer.singleUserReviewStep">Passo de avaliador único</message> - <message key="xmlui.XMLWorkflow.selectSingleReviewer.singleUserReviewStep.singleuserreviewaction">Avaliar submissão</message> - - <message key="xmlui.XMLWorkflow.scoreReview.scoreReviewStep.claimaction">Pontuação de avaliação</message> - <message key="xmlui.XMLWorkflow.scoreReview.scoreReviewStep.scorereviewaction">Pontuação de avaliação</message> - <message key="xmlui.XMLWorkflow.scoreReview.scoreReviewStep">Pontuação de avaliação</message> - - - <message key="xmlui.structure.AboutRepositoryTitle">Sobre o repositório</message> - <message key="xmlui.structure.AboutRepositoryTrail">Sobre o repositório</message> - <message key="xmlui.structure.AboutRepositoryText">Para modificar o conteúdo desta pagina, edite os arquivos de internacionalização e adicione seu próprio texto ao titulo, trail e corpo.</message> - - -<!-- 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> - - -</catalogue> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/Participatorio.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/Participatorio.xsl deleted file mode 100644 index bba87cea3f24d44c0635ba43605782b3033f3478..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/Participatorio.xsl +++ /dev/null @@ -1,46 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - 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/ - ---> -<!-- - TODO: Describe this XSL file - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:import href="../dri2xhtml-alt/dri2xhtml.xsl"/> - <xsl:import href="lib/xsl/core/global-variables.xsl"/> - <xsl:import href="lib/xsl/core/page-structure.xsl"/> - <xsl:import href="lib/xsl/core/navigation.xsl"/> - <xsl:import href="lib/xsl/core/elements.xsl"/> - <xsl:import href="lib/xsl/core/forms.xsl"/> - <xsl:import href="lib/xsl/core/attribute-handlers.xsl"/> - <xsl:import href="lib/xsl/core/utils.xsl"/> - <xsl:import href="lib/xsl/aspect/general/choice-authority-control.xsl"/> - <xsl:import href="lib/xsl/aspect/administrative/administrative.xsl"/> - <xsl:import href="lib/xsl/aspect/artifactbrowser/item-list.xsl"/> - <xsl:import href="lib/xsl/aspect/artifactbrowser/item-view.xsl"/> - <xsl:import href="lib/xsl/aspect/artifactbrowser/community-list.xsl"/> - <xsl:import href="lib/xsl/aspect/artifactbrowser/collection-list.xsl"/> - <xsl:output indent="yes"/> - - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/@mirelogo-small.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/@mirelogo-small.png deleted file mode 100644 index 777bf343dd6879b525597877255e25dd9e5ce773..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/@mirelogo-small.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Crystal_Clear_action_lock3_64px.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Crystal_Clear_action_lock3_64px.png deleted file mode 100644 index 2a1412bb93b23a885ae97ce3a1f509ebda62f2f5..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Crystal_Clear_action_lock3_64px.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio.png deleted file mode 100644 index 0c87249b543576ee238c9303b1e6a4ad3d33fae9..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio_2.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio_2.png deleted file mode 100644 index 7775768174e50f391622a3ea1d170dffc5c9fb10..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/Logo_participatorio_2.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/apple-touch-icon.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/apple-touch-icon.png deleted file mode 100644 index cb944d4236dd56db15dbf8abb30f61b09ff79038..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/apple-touch-icon.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_down_ffffff_16x16.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_down_ffffff_16x16.png deleted file mode 100644 index 213e364252df54dcc571c33e94145adafec7c9ad..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_down_ffffff_16x16.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_up_ffffff_16x16.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_up_ffffff_16x16.png deleted file mode 100644 index 2d9ce05f87760356a3553b76327a22083bef0967..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/arrow_up_ffffff_16x16.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-errortriangle.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-errortriangle.gif deleted file mode 100644 index 77ecac66969b515012f75bda1d7b690d478015ae..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-errortriangle.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-lightning.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-lightning.gif deleted file mode 100644 index 5f4582668679437fba6ad34276756e282f092163..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-lightning.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-warntriangle.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-warntriangle.gif deleted file mode 100644 index 03f658fd18ec14f5f6218bdf9d08248c29134392..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/2-warntriangle.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-circleslash.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-circleslash.gif deleted file mode 100644 index c834095ba81096e161a428b5f3feb7b21c0ed72b..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-circleslash.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-flag.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-flag.gif deleted file mode 100644 index 35857f994003c7bf2b15de407f28f5079b30041b..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-flag.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb1.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb1.gif deleted file mode 100644 index 8fec573875f5f0c0f87cd30bf7cc6823cbd2450a..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb1.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb2.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb2.gif deleted file mode 100644 index ee6aea8f2184abe04685ba5e9afb5ede09080f73..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/3-thumb2.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-question.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-question.gif deleted file mode 100644 index 7b20d616f67eda899aaf3234a2cee87fb52746a3..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-question.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-star.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-star.gif deleted file mode 100644 index da6654c3fcc22c6522821652b113107b6ccbe023..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/4-star.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-pinion.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-pinion.gif deleted file mode 100644 index e48a5e035e4735cb70a8c9a1734d6a874b57de31..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-pinion.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-star.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-star.gif deleted file mode 100644 index 55e8b079a353ac5ea326a9ec878b5ca003ba9964..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/5-star.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-greencheck.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-greencheck.gif deleted file mode 100644 index 91f949b40ce4afe8c1f64d8d879e54bb6bc24bb9..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-greencheck.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-star.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-star.gif deleted file mode 100644 index de8f2fa587c77fd346c9322a67fef6c27f423a55..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-star.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb1.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb1.gif deleted file mode 100644 index 3233f650bd69272ef00c864f42f9b35415b0ed66..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb1.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb2.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb2.gif deleted file mode 100644 index 7fdc37091acda8899440a364889d54e99e385983..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/6-thumb2.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/bug.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/bug.png deleted file mode 100644 index 2d5fb90ec6ee08f53947e0266a87b03f75893446..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/bug.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/readme.txt b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/readme.txt deleted file mode 100644 index c91e09d0bea413afd572f9700d36f7bec34f3f40..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/confidence/readme.txt +++ /dev/null @@ -1,53 +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/ -==== -16x16 Free Application Icons - -This icon set is free for use in personal and commercial projects. - -License Agreement - -By purchasing icons from Aha-Soft, You (the purchaser) -agree to the terms of this agreement, as detailed below. - -You may use the icons from Aha-Soft in commercial and -personal design projects, software or Internet products. -Icons can be displayed in documentation, help files, and -advertising materials. You are free to sell and distribute -products and projects using purchased icons without further -royalty fees. - -All icon files are provided 'as is'. Aha-Soft cannot be -held liable for any negative issues that may occur as a -result of using the icons. - -You agree that all ownership and copyright of the icons -remains the property of Aha-Soft. You may not resell, -distribute, lease, license or sub-license the icons or -modified icons (or a subset of the icons), to any third -party unless they are incorporated into your software or -design products. - -If you have any questions regarding copyright or licensing, -including whether another license is required for icon use -within products, please contact us here: www.aha-soft.com/support.htm - -Product page: http://www.small-icons.com/stock-icons/16x16-free-application-icons.htm - -Icon Design Service - -We can design custom icons for you. Please find the basic information -about ordering icons, pricing and the portfolio here: -www.aha-soft.com/customdev/design.htm - - -Notice -Web-site small-icons.com belongs to Aha-Soft. - -Support page: http://www.aha-soft.com/support.htm - -Copyright � 2009 Aha-Soft. All rights reserved. \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/invisible.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/invisible.gif deleted file mode 100644 index 17d43908d5e11c5b86aee7d90287efdcc27877b2..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/invisible.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/lookup-indicator.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/lookup-indicator.gif deleted file mode 100644 index 3288d1035d70bb86517e2c233f1a904e41f06b29..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/lookup-indicator.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/suggest-indicator.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/suggest-indicator.gif deleted file mode 100644 index d0bce1542342e912da81a2c260562df172f30d73..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/suggest-indicator.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/unlock24.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/unlock24.png deleted file mode 100644 index fae950dcd32f1da2c3b2f9e0ddb2abbf61c00e46..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/authority_control/unlock24.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-ai.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-ai.png deleted file mode 100644 index 3dc7b7750526f2fad46a546bb60315222ab81797..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-ai.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-brasil.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-brasil.png deleted file mode 100644 index 4bc21de82d8eca60d37179fa04b54e8a2724417e..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-brasil.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.gif deleted file mode 100644 index 4660c711d8617f030e481eec5cd0dc6962eb3f74..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.png deleted file mode 100644 index 5514710ea4f6a696818f487f72e5e2a4dfcdd054..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/barra-brasil-v3-bgx.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/bg_participatorio.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/bg_participatorio.png deleted file mode 100644 index 09aa0254d934875fe1ec507ce878c2bde67abb3e..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/bg_participatorio.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/cc-ship.gif b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/cc-ship.gif deleted file mode 100644 index 0f53bce152b0a68bffdaeee666f224637eb3feff..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/cc-ship.gif and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_closed_222222.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_closed_222222.png deleted file mode 100644 index e7ab014d4a0157c873bbeea87f24ce58f0d5afea..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_closed_222222.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_doc_222222.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_doc_222222.png deleted file mode 100644 index 5a6f9d61ccf699d9d5f7e5880f79de067af5f896..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_doc_222222.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_open_222222.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_open_222222.png deleted file mode 100644 index 0912becd1303cf688dad0cf27871b9c212013738..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/controlledvocabulary/voc_open_222222.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/favicon.ico b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/favicon.ico deleted file mode 100644 index 213423e15b685d1e2bf9d97b4f59edc045ec5939..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/favicon.ico and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/footer-banner.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/footer-banner.png deleted file mode 100644 index eddebcdcc4f7a09fd39efebc2e7e453d4b307f16..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/footer-banner.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_ffffff_25x25.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_ffffff_25x25.png deleted file mode 100644 index 97d7e566446e9d88cd2670de767d9d4ceeb2b036..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/gear_ffffff_25x25.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/information.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/information.png deleted file mode 100644 index 12cd1aef900803abba99b26920337ec01ad5c267..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/information.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_0_aaaaaa_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_0_aaaaaa_40x100.png deleted file mode 100644 index e425e6e46ebdfe12ca1ef41e6bb245ca73c9b368..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_b6c8d9_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_b6c8d9_40x100.png deleted file mode 100644 index 3cafcbe1d8bc4ef4c428bdc929684fac3ae36a11..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_b6c8d9_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_fff2f2_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_fff2f2_40x100.png deleted file mode 100644 index 71faf2d122ee2cc94adac6f57afed11539acd84f..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_fff2f2_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_ffffff_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_ffffff_40x100.png deleted file mode 100644 index 72d4757363cd56508fb5c0c903a1d24a483cb5fe..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_100_ffffff_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_70_000000_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_70_000000_40x100.png deleted file mode 100644 index 12e01c1042f2b7527539878dca460fd8f47f41c7..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_70_000000_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_1f3f5e_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_1f3f5e_40x100.png deleted file mode 100644 index c84652deb3cc11a4e47aaa7e9c8c88b90429faa4..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_1f3f5e_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_f0f2f5_40x100.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_f0f2f5_40x100.png deleted file mode 100644 index e1b2d11ec9717f2c717201dcb1c9768356b91238..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_flat_75_f0f2f5_40x100.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_55_fbf9ee_1x400.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_55_fbf9ee_1x400.png deleted file mode 100644 index ad3d6346e00f246102f72f2e026ed0491988b394..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_55_fbf9ee_1x400.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_65_ffffff_1x400.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_65_ffffff_1x400.png deleted file mode 100644 index 8569c1bc9f4bf246dc663bca9d4b74971abbbc3b..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-bg_glass_65_ffffff_1x400.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_2e83ff_256x240.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_2e83ff_256x240.png deleted file mode 100644 index 7a3c7790da5690cf66112921ad6f65d89a718d67..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_444444_256x240.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_444444_256x240.png deleted file mode 100644 index cfd1eaffaae0f5fe30d8e86d2e54b990d2a1ccd0..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_444444_256x240.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_c22121_256x240.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_c22121_256x240.png deleted file mode 100644 index df725f9ed25e47acf29b9692a8fcf29664fa043a..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_c22121_256x240.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_ffffff_256x240.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_ffffff_256x240.png deleted file mode 100644 index 99c18f789a8da9698c4c95411833ab2d1c4d94b0..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/jquery_ui/ui-icons_ffffff_256x240.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/mime.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/mime.png deleted file mode 100644 index 92668ab5ea1b0c317687432c0dc785b8c0b5a416..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/mime.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_DSPACE.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_DSPACE.png deleted file mode 100644 index e6cc643cd9fe011388ad4dc670827b1bfb20bad3..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_DSPACE.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_c3sl.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_c3sl.png deleted file mode 100644 index a55c7ad46fa5144236b6208085166352ee80b0b1..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/powered_by_c3sl.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/search_icon_ffffff_20x20.png b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/search_icon_ffffff_20x20.png deleted file mode 100644 index e652b5536e891d6c16fea1b255d59bfb7970869f..0000000000000000000000000000000000000000 Binary files a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/images/search_icon_ffffff_20x20.png and /dev/null differ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/HTML5Doctor_CSS_Reset.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/HTML5Doctor_CSS_Reset.LICENSE deleted file mode 100644 index 02cee6172794d9d4a5b44ae3df8cd9ccbfe5196a..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/HTML5Doctor_CSS_Reset.LICENSE +++ /dev/null @@ -1,6 +0,0 @@ -HTML5Doctor CSS Reset Stylesheet (reset.css) is released in the public domain. -http://html5doctor.com/html-5-reset-stylesheet/ - --- - -Copyright (C) 2010 Richard Clark, http://richclarkdesign.com/ diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/authority-control.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/authority-control.css deleted file mode 100644 index a02734f2ab9912f1cfd1f6419456d21f1e4def57..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/authority-control.css +++ /dev/null @@ -1,88 +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/ - */ -/** Additions for Authority Control elements **/ -/* for scriptaculous autocomplete */ -div.autocomplete { - display: none; -} - -div.autocomplete, ul.ui-menu { - position:absolute; - width:250px; - background-color:white; - border:1px solid #888; - margin:0; - padding:0; -} -div.autocomplete ul, ul.ui-menu { - list-style-type:none; - margin:0; - padding:0; -} -div.autocomplete ul li.selected { background-color: #ffb;} -div.autocomplete ul li, ul.ui-menu li { - list-style-type:none; - display:block; - margin:0; - padding:2px; -/* height:32px; */ - cursor:pointer; -} -div.autocomplete ul li span.value { display:none; } -ul.ui-menu li a { - display: block; -} -ul.ui-menu li a.ui-state-hover { - background-color: #ffb; -} -/* this magic gets the 16x16 icon to show up.. setting height/width didn't - do it, but adding padding actually made it show up. */ -img.ds-authority-confidence -{ width: 16px; height: 16px; margin: 0px 2px; padding: 0px; vertical-align: bottom; display: inline-block;} - -img.ds-authority-confidence.cf-unset - { background: transparent url(../../images/authority_control/confidence/bug.png); } -img.ds-authority-confidence.cf-novalue - /* { background: transparent } */ - { background: transparent url(../../images/authority_control/confidence/3-circleslash.gif); } -img.ds-authority-confidence.cf-rejected, -img.ds-authority-confidence.cf-failed - { background: transparent url(../../images/authority_control/confidence/2-errortriangle.gif); } -img.ds-authority-confidence.cf-notfound - { background: transparent url(../../images/authority_control/confidence/3-thumb2.gif); } -img.ds-authority-confidence.cf-ambiguous - { background: transparent url(../../images/authority_control/confidence/4-question.gif); } -img.ds-authority-confidence.cf-uncertain - { background: transparent url(../../images/authority_control/confidence/5-pinion.gif); } -img.ds-authority-confidence.cf-accepted - { background: transparent url(../../images/authority_control/confidence/6-thumb2.gif); } - -/* hide authority-value inputs in forms */ -input.ds-authority-value { display:none; } -/** XXX Change to this to get the authority value to show up for debugging: - input.ds-authority-value { display:inline; } -**/ - -/* ..except, show authority-value inputs in on the Item EditMetadata page */ -input.ds-authority-value.ds-authority-visible { display: inline; } - -/* for lock button */ -input.ds-authority-lock - { vertical-align: bottom; height: 24px; width: - 24px; background-repeat: no-repeat; background-color: transparent; } -input.ds-authority-lock.is-locked - { background-image: url(../../images/authority_control/lock24.png); } -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/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/base.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/base.css deleted file mode 100644 index 968e29c194b7d1645b542f58e6136e29a2704c68..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/base.css +++ /dev/null @@ -1,81 +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/ - */ -/* - * base.css - * - * minimal base styles - */ - - -/* #444 looks better than black: twitter.com/H_FJ/statuses/11800719859 */ -body, select, input, textarea { color:#444; } - -/* www.aestheticallyloyal.com/public/optimize-legibility/ */ -h1,h2,h3,h4,h5,h6 { font-weight: bold; text-rendering: optimizeLegibility; } - -/* maxvoltar.com/archive/-webkit-font-smoothing */ -html { -webkit-font-smoothing: antialiased; } - - -/* Accessible focus treatment: people.opera.com/patrickl/experiments/keyboard/test */ -a:hover, a:active { outline: none; } - -a, a:active, a:visited { color:#607890; } -a:hover { color:#036; } - - -ul { margin-left:30px; } -ol { margin-left:30px; list-style-type: decimal; } - -small { font-size:85%; } -.bold, strong, th { font-weight: bold; } - -td, td img { vertical-align:top; } - -sub { vertical-align: sub; font-size: smaller; } -sup { vertical-align: super; font-size: smaller; } - -pre { - padding: 15px; - - /* www.pathf.com/blogs/2008/05/formatting-quoted-code-in-blog-posts-css21-white-space-pre-wrap/ */ - white-space: pre; /* CSS2 */ - white-space: pre-wrap; /* CSS 2.1 */ - white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ - word-wrap: break-word; /* IE */ -} - -/* align checkboxes, radios, text inputs with their label - by: Thierry Koblentz tjkdesign.com/ez-css/css/base.css */ -input[type="radio"] { vertical-align: text-bottom; } -input[type="checkbox"] { vertical-align: bottom; *vertical-align: baseline; } -.ie6 input { vertical-align: text-bottom; } - -/* hand cursor on clickable input elements */ -label, input[type=button], input[type=submit], button { cursor: pointer; } - - -/* These selection declarations have to be separate. - No text-shadow: twitter.com/miketaylr/status/12228805301 */ -::-moz-selection{ background: #5e9fff; color:#fff; text-shadow: none; } -::selection { background:#5e9fff; color:#fff; text-shadow: none; } - -/* j.mp/webkit-tap-highlight-color */ -a:link { -webkit-tap-highlight-color: #5e9fff; } - - -/* always force a scrollbar in non-IE */ -html { overflow-y: scroll; } - -/* make buttons play nice in IE: - www.viget.com/inspire/styling-the-button-element-in-internet-explorer/ */ -button { width: auto; overflow: visible; } - -/* bicubic resizing for non-native sized IMG: - code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/ */ -.ie7 img { -ms-interpolation-mode: bicubic; } \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/handheld.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/handheld.css deleted file mode 100644 index c96ee4860aa8bd9079da4e852846b5c6e0ae72fc..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/handheld.css +++ /dev/null @@ -1,14 +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/ - */ - -* { - float: none; /* Screens are not big enough to account for floats */ - font-size: 80%; /* Slightly reducing font size to reduce need to scroll */ - background: #fff; /* As much contrast as possible */ - color: #000; -} \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/helper.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/helper.css deleted file mode 100644 index 46aff7aed6e70e5e364ccffda4f26fbc69b7e328..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/helper.css +++ /dev/null @@ -1,35 +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/ - */ -/* - * helper.css - * - * Non-semantic helper classes - */ - -/* for image replacement */ -.ir { display:block; text-indent:-999em; overflow:hidden; background-repeat: no-repeat; } - -/* Hide for both screenreaders and browsers - css-discuss.incutio.com/wiki/Screenreader_Visibility */ -.hidden { display:none; visibility:hidden; } - -/* Hide only visually, but have it available for screenreaders - www.webaim.org/techniques/css/invisiblecontent/ - Solution from: j.mp/visuallyhidden - Thanks Jonathan Neal! */ -.visuallyhidden { position:absolute !important; - clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ - clip: rect(1px, 1px, 1px, 1px); } - -/* Hide visually and from screenreaders, but maintain layout */ -.invisible { visibility: hidden; } - -/* >> The Magnificent CLEARFIX << */ -.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.clearfix { display: inline-block; } -* html .clearfix { height: 1%; } /* Hides from IE-mac \*/ -.clearfix { display: block; } \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/jquery-ui-1.8.15.custom.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/jquery-ui-1.8.15.custom.css deleted file mode 100644 index b5cc06c025ace708dc18a38874050f1985d3f8e9..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/jquery-ui-1.8.15.custom.css +++ /dev/null @@ -1,568 +0,0 @@ -/* - * jQuery UI CSS Framework 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - */ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } -.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } -.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.ui-helper-clearfix { display: inline-block; } -/* required comment for clearfix to work in Opera \*/ -* html .ui-helper-clearfix { height:1%; } -.ui-helper-clearfix { display:block; } -/* end clearfix */ -.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { cursor: default !important; } - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - - -/* - * jQuery UI CSS Framework 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Theming/API - * - * To view and modify this theme, visit http://jqueryui.com/themeroller/?ctl=themeroller&ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=0&bgColorHeader=f0f2f5&bgTextureHeader=01_flat.png&bgImgOpacityHeader=75&borderColorHeader=d8e8eb&fcHeader=444444&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=100&borderColorContent=9cacba&fcContent=444444&iconColorContent=444444&bgColorDefault=B6C8D9&bgTextureDefault=01_flat.png&bgImgOpacityDefault=100&borderColorDefault=9cacba&fcDefault=444444&iconColorDefault=444444&bgColorHover=1f3f5e&bgTextureHover=01_flat.png&bgImgOpacityHover=75&borderColorHover=1f3f5e&fcHover=ffffff&iconColorHover=ffffff&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=9cacba&fcActive=444444&iconColorActive=444444&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fff2f2&bgTextureError=01_flat.png&bgImgOpacityError=100&borderColorError=c22121&fcError=c22121&iconColorError=c22121&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=75&bgColorShadow=000000&bgTextureShadow=01_flat.png&bgImgOpacityShadow=70&opacityShadow=0&thicknessShadow=0px&offsetTopShadow=12px&offsetLeftShadow=8px&cornerRadiusShadow=5px - */ - - -/* Component containers -----------------------------------*/ -.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; } -.ui-widget .ui-widget { font-size: 1em; } -.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #9cacba; background: #ffffff url(../../images/jquery_ui/ui-bg_flat_100_ffffff_40x100.png) 50% 50% repeat-x; color: #444444; } -.ui-widget-content a { color: #444444; } -.ui-widget-header { border: 1px solid #d8e8eb; background: #f0f2f5 url(../../images/jquery_ui/ui-bg_flat_75_f0f2f5_40x100.png) 50% 50% repeat-x; color: #444444; font-weight: bold; } -.ui-widget-header a { color: #444444; } - -/* Interaction states -----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #9cacba; background: #b6c8d9 url(../../images/jquery_ui/ui-bg_flat_100_b6c8d9_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #444444; } -.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #444444; text-decoration: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #1f3f5e; background: #1f3f5e url(../../images/jquery_ui/ui-bg_flat_75_1f3f5e_40x100.png) 50% 50% repeat-x; font-weight: normal; color: #ffffff; } -.ui-state-hover a, .ui-state-hover a:hover { color: #ffffff; text-decoration: none; } -.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #9cacba; background: #ffffff url(../../images/jquery_ui/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #444444; } -.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #444444; text-decoration: none; } -.ui-widget :active { outline: none; } - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(../../images/jquery_ui/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; } -.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #c22121; background: #fff2f2 url(../../images/jquery_ui/ui-bg_flat_100_fff2f2_40x100.png) 50% 50% repeat-x; color: #c22121; } -.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #c22121; } -.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #c22121; } -.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } -.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } -.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(../../images/jquery_ui/ui-icons_444444_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_444444_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_444444_256x240.png); } -.ui-state-default .ui-icon { background-image: url(../../images/jquery_ui/ui-icons_444444_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_ffffff_256x240.png); } -.ui-state-active .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_444444_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(../../images/jquery_ui/ui-icons_c22121_256x240.png); } - -/* positioning */ -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-start { background-position: -80px -160px; } -/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -khtml-border-top-left-radius: 0; border-top-left-radius: 0; } -.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; -khtml-border-top-right-radius: 0; border-top-right-radius: 0; } -.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; -khtml-border-bottom-left-radius: 0; border-bottom-left-radius: 0; } -.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; -khtml-border-bottom-right-radius: 0; border-bottom-right-radius: 0; } - -/* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(../../images/jquery_ui/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .75;filter:Alpha(Opacity=75); } -.ui-widget-shadow { margin: 12px 0 0 8px; padding: 0px; background: #000000 url(../../images/jquery_ui/ui-bg_flat_70_000000_40x100.png) 50% 50% repeat-x; opacity: 0;filter:Alpha(Opacity=0); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/* - * jQuery UI Resizable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Resizable#theming - */ -.ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block; } -.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } -.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } -.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } -.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } -.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* - * jQuery UI Selectable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectable#theming - */ -.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; } -/* - * jQuery UI Accordion 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion#theming - */ -/* IE/Win - Fix animation bug - #4615 */ -.ui-accordion { width: 100%; } -.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } -.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } -.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; } -.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; } -.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } -.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; } -.ui-accordion .ui-accordion-content-active { display: block; } -/* - * jQuery UI Autocomplete 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete#theming - */ -.ui-autocomplete { position: absolute; cursor: default; } - -/* workarounds */ -* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */ - -/* - * jQuery UI Menu 1.8.15 - * - * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Menu#theming - */ -.ui-menu { - list-style:none; - padding: 2px; - margin: 0; - display:block; - float: left; -} -.ui-menu .ui-menu { - margin-top: -3px; -} -.ui-menu .ui-menu-item { - margin:0; - padding: 0; - zoom: 1; - float: left; - clear: left; - width: 100%; -} -.ui-menu .ui-menu-item a { - text-decoration:none; - display:block; - padding:.2em .4em; - line-height:1.5; - zoom:1; -} -.ui-menu .ui-menu-item a.ui-state-hover, -.ui-menu .ui-menu-item a.ui-state-active { - font-weight: normal; - margin: -1px; -} -/* - * jQuery UI Button 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button#theming - */ -.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */ -.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */ -button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */ -.ui-button-icons-only { width: 3.4em; } -button.ui-button-icons-only { width: 3.7em; } - -/*button text element */ -.ui-button .ui-button-text { display: block; line-height: 1.4; } -.ui-button-text-only .ui-button-text { padding: .4em 1em; } -.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } -.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } -.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } -.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } -/* no icon support for input elements, provide padding by default */ -input.ui-button { padding: .4em 1em; } - -/*button icon element(s) */ -.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } -.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } -.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } -.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } -.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } - -/*button sets*/ -.ui-buttonset { margin-right: 7px; } -.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } - -/* workarounds */ -button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */ -/* - * jQuery UI Dialog 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog#theming - */ -.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; } -.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } -.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; } -.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } -.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } -.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } -.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } -.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } -.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } -.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } -.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } -.ui-draggable .ui-dialog-titlebar { cursor: move; } -/* - * jQuery UI Slider 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider#theming - */ -.ui-slider { position: relative; text-align: left; } -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } - -.ui-slider-horizontal { height: .8em; } -.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; }/* - * jQuery UI Tabs 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs#theming - */ -.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ -.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; } -.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } -.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ -.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } -.ui-tabs .ui-tabs-hide { display: none !important; } -/* - * jQuery UI Datepicker 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker#theming - */ -.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } -.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } -.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } -.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } -.ui-datepicker .ui-datepicker-prev { left:2px; } -.ui-datepicker .ui-datepicker-next { right:2px; } -.ui-datepicker .ui-datepicker-prev-hover { left:1px; } -.ui-datepicker .ui-datepicker-next-hover { right:1px; } -.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } -.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } -.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; } -.ui-datepicker select.ui-datepicker-month-year {width: 100%;} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { width: 49%;} -.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } -.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } -.ui-datepicker td { border: 0; padding: 1px; } -.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } -.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } -.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { width:auto; } -.ui-datepicker-multi .ui-datepicker-group { float:left; } -.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } -.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } -.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } -.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; } - -/* RTL support */ -.ui-datepicker-rtl { direction: rtl; } -.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } -.ui-datepicker-rtl .ui-datepicker-group { float:right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } - -/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ -.ui-datepicker-cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 200px; /*must have*/ - height: 200px; /*must have*/ -}/* - * jQuery UI Progressbar 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar#theming - */ -.ui-progressbar { height:2em; text-align: left; } -.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/media.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/media.css deleted file mode 100644 index bb5a42ef22922650acba0aea64e5a9b1c4d9b518..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/media.css +++ /dev/null @@ -1,29 +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/ - */ -/* - * Media queries for responsive design - */ - -@media all and (orientation:portrait) { - /* Style adjustments for portrait mode goes here */ - -} - -@media all and (orientation:landscape) { - /* Style adjustments for landscape mode goes here */ - -} - -/* Grade-A Mobile Browsers (Opera Mobile, iPhone Safari, Android Chrome) - Consider this: www.cloudfour.com/css-media-query-for-mobile-is-fools-gold/ */ -@media screen and (max-device-width: 480px) { - - - /* Prevent iOS, WinMobile from adjusting font size */ - html { -webkit-text-size-adjust:none; -ms-text-size-adjust:none; } -} \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/print.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/print.css deleted file mode 100644 index 96eada22a28cc40df173958051a416928940dbcc..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/print.css +++ /dev/null @@ -1,34 +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/ - */ -/* - * print.css - * - * print styles - */ -* { background: transparent !important; color: #444 !important; text-shadow: none; } - -a, a:visited { color: #444 !important; text-decoration: underline; } - -a:after { content: " (" attr(href) ")"; } - -abbr:after { content: " (" attr(title) ")"; } - -.ir a:after { content: ""; } /* Don't show links for images */ - -pre, blockquote { border: 1px solid #999; page-break-inside: avoid; } - -img { page-break-inside: avoid; } - -@page { margin: 0.5cm; } - -p, h2, h3 { orphans: 3; widows: 3; } - -h2, h3{ page-break-after: avoid; } - -#no-js-warning-wrapper{ display: none; visibility: hidden; } - diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/reset.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/reset.css deleted file mode 100644 index ff36bc85329337ff4896a1af51d36cc58c6fb849..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/reset.css +++ /dev/null @@ -1,87 +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/ - */ -/* - reset.css -*/ - - - -/* - html5doctor.com Reset Stylesheet (Eric Meyer's Reset Reloaded + HTML5 baseline) - v1.4 2009-07-27 | Authors: Eric Meyer & Richard Clark - html5doctor.com/html-5-reset-stylesheet/ -*/ -html, body, div, span, object, iframe, -h1, h2, h3, h4, h5, h6, p, blockquote, pre, -abbr, address, cite, code, -del, dfn, em, img, ins, kbd, q, samp, -small, strong, sub, sup, var, -b, i, -dl, dt, dd, ol, ul, li, -fieldset, form, label, legend, -table, caption, tbody, tfoot, thead, tr, th, td, -article, aside, figure, footer, header, -hgroup, menu, nav, section, menu, -time, mark, audio, video { - margin:0; - padding:0; - border:0; - outline:0; - font-size:100%; - vertical-align:baseline; - background:transparent; -} - -article, aside, figure, footer, header, -hgroup, nav, section { display:block; } - -nav ul { list-style:none; } - -blockquote, q { quotes:none; } - -blockquote:before, blockquote:after, -q:before, q:after { content:''; content:none; } - -a { margin:0; padding:0; font-size:100%; vertical-align:baseline; background:transparent; } - -ins { background-color:#ff9; color:#000; text-decoration:none; } - -mark { background-color:#ff9; color:#000; font-style:italic; font-weight:bold; } - -del { text-decoration: line-through; } - -abbr[title], dfn[title] { border-bottom:1px dotted #000; cursor:help; } - -/* tables still need cellspacing="0" in the markup */ -table { border-collapse:collapse; border-spacing:0; } - -hr { display:block; height:1px; border:0; border-top:1px solid #ccc; margin:1em 0; padding:0; } - -input, select { vertical-align:middle; } - - -/* -fonts.css from the YUI Library: developer.yahoo.com/yui/ - Please refer to developer.yahoo.com/yui/fonts/ for font sizing percentages - -There are three custom edits: - * remove arial, helvetica from explicit font stack - * make the line-height relative and unit-less - * remove the pre, code styles -*/ -body { font:13px sans-serif; *font-size:small; *font:x-small; line-height:1.22; } - -table { font-size:inherit; font:100%; } - -select, input, textarea { font:99% sans-serif; } - - -/* normalize monospace sizing - * en.wikipedia.org/wiki/MediaWiki_talk:Common.css/Archive_11#Teletype_style_fix_for_Chrome - */ -pre, code, kbd, samp { font-family: monospace, sans-serif; } \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/style.css b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/style.css deleted file mode 100644 index a231193f86a04d44fdc10bd848725a40faf01028..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/style.css +++ /dev/null @@ -1,1506 +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/ - */ -/* - * style.css - * - * Primary Styles - */ - -/*Font size percentages based on the tables at developer.yahoo.com/yui/fonts/ */ -h1 { - font-size: 182%; - color: #1F3F5E; - text-align: justify; -} - -h2{ - font-size: 123.1%; -} - -h3 { - font-size: 116%; - -} - -h4 { - font-size: 108%; -} - -h5, h6 { - font-size: 100%; -} - -body { - background: url('../../images/bg_participatorio.png'); -} - -/*fix for firefox in os x, where selects get the incorrect -height if it's not explicitly set this shouldn't be noticeable in -other browsers*/ -select { - height: 20px; -} - -select.multiple { - height: auto; -} - -#ds-header-wrapper { - color: white; - min-width: 950px; - padding-top: 30px; -} - -#ds-header-logo-link { - text-decoration: none; - cursor: pointer; -} - -#ds-header-logo { - float:left; - width: 300px; - height: 113px; - margin-top: 0px; - margin-right: 15px; - background: url('../../images/Logo_participatorio_2.png'); - background-repeat: no-repeat; - background-color: transparent; - background-size: 100%; -} - -#ds-header-logo-text { - font-size: 400%; - color: white; - line-height: 70px; - font-weight: normal; - vertical-align: middle; - float: left; -} - -#barra-brasil { - position: absolute; - overflow: hidden; - width: 100%; - background: #004b82 url('../../images/barra-brasil-v3-bgx.png') center bottom no-repeat; - left: 0; -} -#barra-brasil .barra { - display: block; - width: 960px; - height: 28px; - margin: 0 auto; - background: url('../../images/barra-brasil-v3-bgx.gif') 0 bottom repeat-x; -} -#barra-brasil .barra ul { - float: right; - width: 319px; - height: 28px; - list-style: none; - margin: 0px; -} -#barra-brasil .barra ul li { - float: left; - padding-left: 25px; - list-style: none; - margin: 0px; -} -#barra-brasil-ai { - display: block; - width: 161px; - height: 28px; - text-indent: -1000px; - background: #004b82 url('../../images/barra-brasil-ai.png') no-repeat 0 4px; -} -#barra-brasil-brasilgov { - display: block; - width: 108px; - height: 28px; - text-indent: -1000px; - background: #004b82 url('../../images/barra-brasil-brasil.png') no-repeat 0 4px; -} - -#ds-header-ds-user-box { - right: 0; - top: 10px; - position: absolute; - color: white; -} - -#ds-user-box a{ - color: #555; -} - -#ds-trail-wrapper { - margin: 0; - padding: 0; - min-width: 950px; -} - -#ds-trail { - background-color: #EFEFEF; - list-style: none; - line-height: 138.5%; - margin: 0; - padding: 3px 0; - border: 2px solid white; - border-radius: 6px; -} - -#ds-trail li { - display: inline; - color: #1F3F5E; - margin-right: 5px; -} -#ds-trail .ds-trail-link.first-link { - padding-left: 10px; -} - -#ds-trail a { - color: #1F3F5E; -} - -#ds-language-selection { - float: right; - margin-right: 5px; -} - -#no-js-warning, -#ds-trail, -#ds-header, -#ds-footer, -#ds-content { - width: 950px; - margin: auto; - position: relative; -} - -/*ie6 uses quirks mode for strict xhtml pages, and in quirks mode margin: auto; doesn't center things*/ -.ie6 #no-js-warning-wrapper, -.ie6 #ds-trail-wrapper, -.ie6 #ds-header-wrapper, -.ie6 #ds-footer-wrapper, -.ie6 #ds-content-wrapper { - text-align: center; -} - -.ie6 #ds-trail, -.ie6 #ds-header, -.ie6 #ds-footer, -.ie6 #ds-content { - margin: 0; - text-align: left; -} - -#ds-footer-wrapper { - margin-top: 40px; -} - -#ds-footer { - padding-top: 10px; - font-size: 93%; - line-height: 1.6em; -} - -#ds-footer-left { - float: left; -} - -#ds-footer-right { - float:right; -} - -#ds-footer-right span.theme-by{ - display: inline-block; - vertical-align: top; -} - -#ds-footer-logo-link { - text-decoration:none; - line-height: 40px; - cursor: pointer; -} - -#ds-footer-logo { - display: inline-block; - background: url('../../images/@mirelogo-small.png'); - background-repeat: no-repeat; - width: 79px; - height: 40px; -} - -#ds-footer-links { - clear: left; -} - -.ie6 #ds-footer-links { - display: inline; -} - -#ds-footer-banner{ - height: 109px; - width: 950px; - background:url('../../images/footer-banner.png'); - background-size: 100%; -} -#ds-footer-powered{ - float: right; - clear: both; - width: 222px; - height: 40px; -} -#ds-footer-powered ul { - float: right; - width: 222px; - height: 15px; - list-style: none; - margin: 0px; -} -#ds-footer-powered ul li { - float: left; - padding-left: 5px; - list-style: none; - margin: 0px; -} -#ds-footer-c3sl{ - display: block; - width: 106px; - height: 15px; - text-indent: -1000px; - background:url('../../images/powered_by_c3sl.png'); - background-repeat: no-repeat; - background-size: 100%; -} -#ds-footer-dspace{ - display: block; - width: 106px; - height: 15px; - text-indent: -1000px; - background:url('../../images/powered_by_DSPACE.png'); - background-repeat: no-repeat; - background-size: 100%; -} - - - -/*make transparent PNGs invisible in IE6 until PNG-fix is applied*/ -.ie6 #ds-header-logo, -.ie6 #ds-footer-logo { - visibility: hidden; -} - - -#ds-body { - float: left; - width: 665px; - margin-top: 10px; - padding: 10px; - background-color: #EFEFEF; - border: 2px solid white; - border-radius: 6px; - box-shadow: 1px 1px 6px #CCC; -} - -#ds-options-wrapper { - float: right; - width: 249px; - padding-top:10px; -} - -#ds-options { - padding: 0; - background-color: #EFEFEF; - border: 2px solid white; - border-radius: 6px; - box-shadow: 1px 1px 6px #CCC; -} - -h1.ds-option-set-head { - margin-top: 20px; - padding: 3px 10px; - font-size: 108%; - border-top: 1px dotted #CCCCCC; -} - -#ds-search-option-head{ - margin-top: 0; - border-top: none; -} - -div.ds-option-set { - border-top: 0px none #CCCCCC; -} - -div.ds-option-set ul { - list-style: none; - margin-left: 10px; - padding-top: 5px; - padding-bottom: 5px; -} - -div.ds-option-set .ds-sublist-head { - font-weight: normal; - font-size: 100%; -} - -div.ds-option-set ul.sublist { - margin-left: 20px; - padding-top: 0; - padding-bottom: 0; -} - -div#ds-feed-option li -{ - padding-top: 4px; -} - -div#ds-feed-option a -{ - padding: 0px 0px 2px 20px; -} - -#ds-search-option { - padding: 10px; -} - -#ds-search-form { - margin-bottom: 10px; -} - -#ds-search-form input.ds-text-field{ - width: 169px; -} - -#ds-search-form input.ds-button-field { - margin-left: 6px; -} - -#ds-search-form input.ds-text-field, -#ds-search-form input.ds-button-field{ - margin-bottom: 10px; - border: 1px solid black; - border-radius: 11px; -} - -p { - margin-bottom: 10px; -} - -#aspect_eperson_EditProfile_list_form, -.submission fieldset.ds-form-list, -.administrative fieldset.ds-form-list { - margin-bottom: 25px; -} - -.primary { - margin-top: 10px; - margin-bottom: 30px; - margin-right: 10px; -} - -ol { - margin: 0; - list-style: none; -} - -th, -td { - padding: 5px; - vertical-align: middle; -} - -.ds-button-field, -#aspect_eperson_StartRegistration_list_registration-progress li { - background-color: #6d859c; - border: 1px solid #1F3F5E; - padding: 2px 5px; - color: #FFFFFF; - font-weight: bold; - cursor: pointer; -} - -.ds-button-field[disabled="disabled"], -.ds-button-field.disabled, -li.button.disabled input { - opacity: 0.35; - cursor: auto; -} - -#aspect_eperson_StartRegistration_list_registration-progress li { - cursor: default; -} - -#aspect_eperson_StartRegistration_list_registration-progress li.arrow { - background-color: inherit; - border: none; - color: inherit; - font-weight: normal; -} - -.ie6 #aspect_eperson_StartRegistration_list_registration-progress li.arrow, -.ie7 #aspect_eperson_StartRegistration_list_registration-progress li.arrow { - background-color: #FFFFFF; - color: #444444; -} - -.ie6 #aspect_eperson_StartRegistration_list_registration-progress li.arrow { - padding-top: 5px; -} - -ul.ds-progress-list { - margin: 0 0 10px 0; - padding: 2px 0; - text-align: center; -} - -ul.ds-progress-list li { - font-weight: bold; - overflow: hidden; - display: inline; - padding: 0; - margin: 0; - max-width: 400px; -} - -ul.ds-progress-list li.button { - padding: 0; -} - -ul.ds-progress-list li.button input.ds-button-field { - font-size: 77%; -} - -.ie6 ul.ds-progress-list li.button input.ds-button-field, -.ie7 ul.ds-progress-list li.button input.ds-button-field { - padding-left: 0; - padding-right: 0; -} - -ul.ds-progress-list li.current input.ds-button-field, -#aspect_eperson_StartRegistration_list_registration-progress li.current { - background-color: #499c73; - border: 1px solid #1f5e3f; -} - -ul.ds-progress-list li.disabled input.ds-button-field -#aspect_eperson_StartRegistration_list_registration-progress li.disabled { - background-color: #F0F2F5; - border: 1px solid #D8E8EB; - color: #444444; - cursor: default; -} - -.ie6 .disabled, -.ie6 li.disabled input, -.ie7 .ds-button-field.disabled, -.ie7 li.button.disabled input, -.ie8 .ds-button-field.disabled, -.ie8 li.button.disabled input { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 50); - zoom: 1; - cursor: auto; -} - - -ul.ds-progress-list li.arrow { - border: none; - background: none; - font-size: 116%; - font-weight: normal; - margin-left: 3px; - margin-right: 3px; -} - -.ie6 ul.ds-progress-list li.arrow { - height: 25px; - width: 25px; - margin: 0; -} - -textarea.ds-textarea-field, -input.ds-text-field, -input.ds-file-field, -input.ds-button-field, -input.ds-password-field { - margin-bottom: 5px; - margin-top: 5px; - font-size: 93%; -} - -textarea.ds-textarea-field, -input.ds-text-field, -input.ds-password-field { - padding: 3px; - border: 1px solid #AAAAAA; -} - -.ie6 input.ds-text-field, -.ie6 input.ds-password-field { - font-size: 85%; - height: 22px; -} - -.submission .ds-form-list input.ds-text-field, -.administrative .ds-form-list input.ds-text-field, -textarea.ds-textarea-field { - width: 500px; -} - -table textarea.ds-textarea-field { - width: 400px; -} - -#aspect_administrative_item_EditItemMetadataForm_field_value { - width: 570px; -} - -#aspect_administrative_registries_EditMetadataSchema_list_edit-schema-new-field-form .ds-text-field, -#aspect_administrative_item_EditItemMetadataForm_field_language, -.ds-composite-component input.ds-text-field { - width: auto; -} - -textarea.ds-textarea-field:focus, -input.ds-text-field:focus, -input.input.ds-password-field:focus { - border-color: #5F9DE4; -} - -/* - * Show a blue glow around a focused text field - * only target browsers that support rgba colors and boxshadows - * see http://www.modernizr.com/docs/ - */ -.rgba.boxshadow textarea.ds-textarea-field:focus, -.rgba.boxshadow input.ds-text-field:focus, -.rgba.boxshadow input.ds-password-field:focus { - -moz-box-shadow:0 0 8px rgba(95, 158, 212, 0.5); - -webkit-box-shadow:0 0 8px rgba(95, 158, 212, 0.5); - box-shadow:0 0 8px rgba(95, 158, 212, 0.5); - border-color:rgba(95, 158, 212, 0.75); - outline:medium none; -} - -span.error { - clear: both; - display: block; - color: #c22121; - font-size: 0.9em; - margin-top: 3px; -} - -textarea.ds-textarea-field.error, -input.ds-text-field.error, -input.ds-password-field.error { - border-color: #c22121; - background-color: #fff2f2; -} - -.rgba.boxshadow textarea.ds-textarea-field.error:focus, -.rgba.boxshadow input.ds-text-field.error:focus, -.rgba.boxshadow input.ds-password-field.error:focus { - -moz-box-shadow:0 0 8px rgba(194, 33, 33, 0.5); - -webkit-box-shadow:0 0 8px rgba(194, 33, 33, 0.5); - box-shadow:0 0 8px rgba(194, 33, 33, 0.5); - border-color:rgba(194, 33, 33, 0.75) !important; - outline:medium none; -} - - -.ds-form-list { - margin-top: 15px; -} - -.submission h2, -.ds-form-list legend{ - font-size: 182%; - margin-bottom: 15px; - color: #1F3F5E; -} - -.ds-form-item legend { - font-size: 100%; - margin:0; - color: inherit; -} - -fieldset ol { - margin: 0; -} - -li.ds-form-item { - list-style: none; - margin-bottom: 35px; - vertical-align: middle !important; - position: relative; - clear: left; -} - -li.ds-form-item.last { - margin-bottom: 0; -} - -li.ds-form-item .ds-form-label{ - font-weight: bold; - font-size: 123.1%; -} - -li.ds-form-item label.ds-composite-component{ - display: block; - float: left; - font-size: 93%; - padding:0 8px 0 0; -} - -li.ds-form-item label.ds-composite-component input.ds-text-field{ - font-size: 100%; - width: 242px; -} - -li.ds-form-item .ds-select-field { - margin-top: 5px; -} - -.ds-add-button, -label.ds-composite-component .ds-select-field { - margin-top: 6px; - margin-bottom: 6px; -} - -li.ds-form-item label.ds-composite-component.last{ - padding:0; -} - -.ds-add-button { - vertical-align: top; - margin-left: 8px; -} - - -.ds-form-content input.ds-button-field { - font-size: 93%; -} - -select#aspect_submission_submit_SelectCollectionStep_field_handle { - max-width: 350px; -} - -#aspect_submission_StepTransformer_field_dc_date_issued_year, -#aspect_submission_StepTransformer_field_dc_date_issued_day { - width: 50px; -} - -#aspect_submission_StepTransformer_field_dc_identifier_value { - width: 130px; - margin-bottom: 0; -} - -span.composite-help, -span.field-help { - display: block; - font-size: 93%; - margin-top: 3px; - width: 506px; - text-align: justify; -} - -.ds-checkbox-field input, -.ds-radio-field input { - margin-left: 0; -} - -.ds-checkbox-field label, -.ds-radio-field label { - margin-right: 3px; -} -/*hide the double label for checkboxes & radio buttons*/ -.ds-checkbox-field legend, -.ds-radio-field legend { - display: none; -} - -.ds-previous-values { - margin-top: 10px; - clear: both; -} - -#aspect_submission_Submissions_div_submissions .ds-static-div, -.submission .ds-form-sublist ol { - background-color: #fafafa; - border: 1px solid #ebebeb; - margin-top: 3px; - margin-bottom: 30px; - padding: 10px; -} - -#aspect_submission_Submissions_div_submissions table, -#aspect_submission_Submissions_div_submissions table tr, -#aspect_submission_Submissions_div_submissions table td, -#aspect_submission_Submissions_div_submissions table th { - background-color: #FFFFFF; - border: 1px solid #9CACBA; -} - -#aspect_submission_Submissions_div_submissions table tr.ds-table-header-row, -#aspect_submission_Submissions_div_submissions table tr.ds-table-header-row th { - background-color: #B6C8D9; - border: 1px solid #9CACBA; - -} - -.submission .ds-form-sublist li.ds-form-item { - margin-bottom: 5px; -} - -.submission .ds-form-sublist .ds-form-label { - font-weight: bold; -} - - -.administrative.tabbed ul.horizontal { - list-style: none; - margin: 15px 0 0; - border-bottom: 1px solid #9cacba; -} - -.administrative.tabbed ul.horizontal li{ - float: left; - border: 1px solid #9cacba; - padding: 5px; - margin-bottom: -1px; - margin-right: 7px; - border-bottom: none; -} - -.administrative.tabbed ul.horizontal li a{ - text-decoration: none; - color: #444444; -} - -.administrative.tabbed ul.horizontal li.active-tab{ - background-color: #fafafa; - z-index: 1; - font-weight: bold; -} - -.pane { - padding: 10px; - clear: both; - background-color: #fafafa; - border: 1px solid #9cacba; - margin-bottom: 25px; - margin-top: 0; -} - -.pane .ds-form-list { - margin-top: 0; -} - -.administrative.tabbed .pane { - border-top: none; -} - -.pagination, -.pagination-masked { - padding: 7px; - background-color: #fafafa; - border: 1px solid #ebebeb; - line-height: 1em; - vertical-align:middle; -} - -.pagination-links { - list-style: none; - float: right; - margin: 0; -} - -.pagination-links li { - display: inline; - padding-left: 2px; - padding-right: 2px; -} - -.current-page-link { - font-weight: bold; - color: #1F3F5E; -} - -.current-page-link a{ - color: #1F3F5E; -} - -.pagination-info { - float: left; - margin:0; -} - -.pagination-masked.top { - margin-top: 5px; -} - -.ds-artifact-list { - list-style: none; - margin: 0; - line-height: 153.9%; -} - -.file-wrapper, -.ds-artifact-item { - padding-top: 15px; - padding-bottom: 15px; -} - -.ds-artifact-item.collection, -.ds-artifact-item.community { - padding-top: 1px; - padding-bottom: 1px; -} - -.community .artifact-title a { - font-weight: bold; -} - -.collection .artifact-title a { - font-weight: normal; -} - -#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser .short-description, #aspect_discovery_SiteRecentSubmissions_div_site-home .short-description { - display: none; -} - -#aspect_artifactbrowser_SimpleSearch_div_search-results li, #aspect_discovery_SimpleSearch_div_search-results li, #aspect_artifactbrowser_AdvancedSearch_div_search-results li { - padding-top: 15px; - padding-bottom: 15px; -} - -#aspect_artifactbrowser_SimpleSearch_div_search-results ul, #aspect_discovery_SimpleSearch_div_search-results ul, #aspect_artifactbrowser_AdvancedSearch_div_search-results ul { - margin-bottom: 25px; -} - -.artifact-title { - font-size: 123.1%; -} - -.result-query, -.artifact-info { - color: gray; -} - -.artifact-abstract { - text-align: justify; -} - -ul.alphabet { - list-style: none; - margin: 0; -} - -ul.alphabet li { - display:inline; -} - -#aspect_eperson_PasswordLogin_list_password-login .ds-form-item { - float: left; - margin: 0; - margin-right: 25px; -} - -#aspect_eperson_PasswordLogin_list_password-login .ds-form-item a { - margin-left: 20px; -} - -#aspect_eperson_PasswordLogin_list_password-login .ds-form-item.last { - clear: left; -} - - -#aspect_eperson_PasswordLogin_list_password-login .ds-form-item.last .ds-form-label{ - display: none; -} - -td select.ds-select-field { - margin-left: 5px; -} - -form.search, -div.discoverySearchBox -{ - background-color: #fafafa; - border: 1px solid #ebebeb; - padding: 10px; - margin-bottom: 15px; -} - -form.search label, -div.discoverySearchBox label -{ - font-weight: bold; -} - -form.search p.ds-paragraph.button-list, -div.discoverySearchBox p.ds-paragraph.button-list -{ - text-align: center; - margin: 0; -} - -form.search fieldset, -div.discoverySearchBox fieldset { - margin: 0; -} - -form.search .ds-form-item, -div.discoverySearchBox .ds-form-item -{ - margin: 0; - padding-bottom: 5px; -} - -form.search .ds-form-item select, -div.discoverySearchBox .ds-form-item select -{ - margin-top: 0; -} - -form.search label.ds-composite-component .ds-select-field, -div.discoverySearchBox label.ds-composite-component .ds-select-field -{ - margin-top: 6px; -} - -form.search .ds-form-item label, -div.discoverySearchBox .ds-form-item label -{ - font-size: 100%; -} - -form.search .ds-form-content, -div.discoverySearchBox .ds-form-content -{ - display: inline; -} - -form.search table input.ds-text-field, -div.discoverySearchBox table input.ds-text-field -{ - margin: 0; -} - -form.search .field-help, -div.discoverySearchBox .field-help -{ - margin: 3px 0; -} - -.collection .search, -.community .search { - margin-top: 25px; -} - -#aspect_discovery_CollectionSearch_p_search-query, -#aspect_discovery_CommunitySearch_p_search-query{ - margin-bottom:0; -} - -.result-query { - margin-bottom: 30px; -} - -#aspect_administrative_registries_EditMetadataSchema_table_metadata-schema-edit-existing-fields, -#aspect_administrative_registries_MetadataRegistryMain_table_metadata-registry-main-table, -#aspect_administrative_registries_FormatRegistryMain_table_bitstream-format-registry, -#aspect_submission_Submissions_table_unfinished-submissions, -#aspect_submission_Submissions_table_submissions-inprogress, -#aspect_submission_Submissions_table_completed-submissions, -table.detailtable { - margin-top: 10px; - margin-bottom: 10px; - border-collapse: collapse; -} - -#aspect_administrative_registries_EditMetadataSchema_table_metadata-schema-edit-existing-fields tr, -#aspect_administrative_registries_MetadataRegistryMain_table_metadata-registry-main-table tr, -#aspect_administrative_registries_FormatRegistryMain_table_bitstream-format-registry tr, -#aspect_submission_Submissions_table_unfinished-submissions tr, -#aspect_submission_Submissions_table_submissions-inprogress tr, -#aspect_submission_Submissions_table_completed-submissions tr, -table.detailtable tr { - line-height: 1.6em; - border: 1px solid #ebebeb; -} - -#aspect_administrative_registries_EditMetadataSchema_table_metadata-schema-edit-existing-fields tr.even, -#aspect_administrative_registries_MetadataRegistryMain_table_metadata-registry-main-table tr.even, -#aspect_administrative_registries_FormatRegistryMain_table_bitstream-format-registry tr.even, -#aspect_submission_Submissions_table_unfinished-submissions tr.even, -#aspect_submission_Submissions_table_submissions-inprogress tr.even, -#aspect_submission_Submissions_table_completed-submissions tr.even, -table.detailtable tr.even { - background-color: #fafafa; -} - -#aspect_administrative_registries_EditMetadataSchema_table_metadata-schema-edit-existing-fields td, -#aspect_administrative_registries_MetadataRegistryMain_table_metadata-registry-main-table td, -#aspect_administrative_registries_FormatRegistryMain_table_bitstream-format-registry td, -#aspect_submission_Submissions_table_unfinished-submissions td, -#aspect_submission_Submissions_table_submissions-inprogress td, -#aspect_submission_Submissions_table_completed-submissions td, -table.detailtable td { - padding: 5px 10px; - text-align: justify; - border: 1px solid #ebebeb; - vertical-align: top; -} - -#aspect_administrative_registries_EditMetadataSchema_table_metadata-schema-edit-existing-fields tr.ds-table-header-row, -#aspect_administrative_registries_MetadataRegistryMain_table_metadata-registry-main-table tr.ds-table-header-row, -#aspect_administrative_registries_FormatRegistryMain_table_bitstream-format-registry tr.ds-table-header-row, -#aspect_submission_Submissions_table_unfinished-submissions tr.ds-table-header-row, -#aspect_submission_Submissions_table_submissions-inprogress tr.ds-table-header-row, -#aspect_submission_Submissions_table_completed-submissions tr.ds-table-header-row { - border: none; -} - - -table.detailtable td.label-cell { - font-weight: bold; - text-align: left; - width: 100px; -} - -div.item-summary-view-metadata h1, -div.item-summary-view-metadata h2 { - line-height: normal; -} - -div.item-summary-view-metadata { - text-align: justify; - line-height: 161.6%; - margin-bottom: 30px; -} - -div.simple-item-view-authors { - font-size: 123.1%; - font-weight: bold; - border-bottom: 1px dotted #CCCCCC; - padding-top: 5px; - padding-bottom: 2px; - margin-bottom: 20px; - text-align: justify; -} - -div.simple-item-view-authors span{ - text-align: justify; -} - -#aspect_artifactbrowser_ItemViewer_div_item-view h2, -div.item-summary-view-metadata p.item-view-toggle-bottom, -div.simple-item-view-description { - margin-top: 20px; -} - -#aspect_artifactbrowser_ItemViewer_div_item-view h2, -div.simple-item-view-description h3{ - border-top: 1px dotted #CCCCCC; - padding-top: 5px; - margin-bottom: 3px; -} - -#aspect_artifactbrowser_ItemViewer_div_item-view h2 { - margin-bottom: 10px; -} - -div.spacer{ - height: 15px; -} - -.thumbnail-wrapper, -.file-metadata, -.file-link { - float: left; - margin-right: 15px; -} - -.item-metadata { - float: left; -} - -.file-metadata { - width: 300px; -} - -.file-metadata span, -.item-metadata span { - float: left; -} - -.item-metadata span.content span { - float: none; -} - -.file-metadata span.bold, -.item-metadata span.bold { - width: 80px; - clear: left; - text-align: right; - margin-right: 7px; -} - -#ds-system-wide-alert, -.notice { - padding: 10px; - margin: 10px 0; - border: 1px solid #bfc221; - background-color: #fffff2; -} - -.notice.success -{ - border-color: #21c221; - background-color: #f2fff2; -} - -#ds-system-wide-alert, -.notice.failure -{ - border-color: #c22121; - background-color: #fff2f2; -} - -#ds-system-wide-alert p { - margin: 0; -} - -#aspect_artifactbrowser_CommunityViewer_div_community-home h2, -#aspect_artifactbrowser_CollectionViewer_div_collection-home h2 { - margin-top: 30px; - margin-bottom: 3px; - border-top: 1px dotted #CCCCCC; - padding-top: 5px; - -} - -.ds-logo-wrapper { - display: block; -} - -#aspect_administrative_item_FindItemForm_list_find-item-form .ds-form-item { - margin:0; -} - -#aspect_administrative_registries_EditMetadataSchema_div_edit-schema-new-field .ds-form-item.last { - margin-top: -25px; -} - -#no-js-warning { - margin-top: 15px; - margin-bottom: 10px; - text-align: center; -} - -form.discover-search-box{ - margin-bottom: 10px; -} - - -form.discover-sort-box select{ - margin: 0 4px; -} - -.hidden { - display:none; - visibility:hidden; -} - -.icon-button{ - padding:4px; - cursor: pointer; - margin: 2px; - background-color: #6D859C; - border: 1px solid #1F3F5E; - text-indent: -1000px; - width: 30px; - height: 30px; - display:block; - /*Required for IE*/ - font-size: 0; - line-height: 0; -} - -.icon-button.arrowUp{ - background-image: url(../../images/arrow_up_ffffff_16x16.png); - background-repeat: no-repeat; - background-position: center center; -} - -.icon-button.arrowDown{ - background-image: url(../../images/arrow_down_ffffff_16x16.png); - background-repeat: no-repeat; - background-position: center center; -} - -/* FOR CC License */ -span.floatleft { - border:none; - float:right; - display:inline; -} - -/* FOR CC PAGE to GROUP ITEMS horizontally */ -ul.horizontal li span.bold a { color: black; } - -/* group items horizontally in a list */ - -ul.horizontalVanilla -{ -font-weight: bold; -list-style-type: none; -padding: 0px; -padding-left: 0px; -padding-bottom: 15px; -border-left: 1px solid white; -border-right: 1px solid white; -margin: 10px -1px 5px -1px; -width: inherit; -} - -ul.horizontalVanilla li -{ -float: left; -height: 100%; -background-color: rgb(255, 255, 255); -margin: 2px 2px 0px 2px; -/* border: 1px solid rgb(240, 240, 210); */ -} - -/* Controlled vocabulary support css START*/ -ul.vocabulary { - margin-left: 0; -} - -ul.vocabulary, -ul.vocabulary ul, -ul.vocabulary li -{ - list-style: none; -} - -ul.vocabulary div.vocabulary-node-icon{ - cursor: pointer; - width: 15px; - height: 12px; - display: inline-block; -} - -ul.vocabulary div.vocabulary-node-icon.vocabulary-doc{ - background-image: url(../../images/controlledvocabulary/voc_doc_222222.png); -} - -ul.vocabulary div.vocabulary-node-icon.vocabulary-open{ - background-image: url(../../images/controlledvocabulary/voc_open_222222.png); -} - -ul.vocabulary div.vocabulary-node-icon.vocabulary-closed{ - background-image: url(../../images/controlledvocabulary/voc_closed_222222.png); - background-repeat: no-repeat; -} - -div.vocabulary-container li.error{ - color: #c22121; -} -/* Controlled vocabulary support css END*/ - -#aspect_administrative_authorization_EditPolicyForm_field_start_date{ - width: 100px; -} -#aspect_administrative_authorization_EditPolicyForm_field_end_date{ - width: 100px; -} -#aspect_administrative_authorization_EditItemPolicies_table_policies-confirm-delete tr, -#aspect_administrative_authorization_EditItemPolicies_table_policies-confirm-delete td -{ - border: 1px solid lightgray; -} - - -#aspect_administrative_authorization_AdvacedAuthorizationsForm_field_end_date{ - width: 100px; -} -#aspect_administrative_authorization_AdvacedAuthorizationsForm_field_start_date{ - width: 100px; -} -#aspect_submission_StepTransformer_field_embargo_until_date{ - width: 100px; -} - -#aspect_administrative_item_AddBitstreamForm_field_embargo_until_date{ - width: 100px; -} - -#aspect_administrative_item_EditBitstreamForm_field_embargo_until_date{ - width: 100px; -} - -#aspect_submission_StepTransformer_table_policies tr, -#aspect_submission_StepTransformer_table_policies td -{ - border: 1px solid lightgray; -} - -table.detailtable { - background-color: #D8E8EB; -} - -table.detailtable th{ - background-color: #F0F2F5; - word-wrap: normal; -} - -table.detailtable td{ - background-color: #FFFFFF; - text-align: right; -} - - -span.highlight{ - font-weight: bold; -} - -div.gear-icon{ - background-image: url('../../images/gear_6D859C_25x25.png'); -} - -ul.gear-selection li.gear-option-selected{ - background: url('../../images/check_606060_15x15.png') no-repeat 3px center; -} - -input#aspect_discovery_SimpleSearch_field_query{ - width: 565px; -} - -input.search-icon{ - background-image: url('../../images/search_icon_ffffff_20x20.png'); - background-repeat: no-repeat; - background-position: center center; - text-indent: -1000px; - /*Css props below are required for IE*/ - font-size: 0; - display:block; - line-height: 0; -} - -div#aspect_discovery_SimpleSearch_div_search p.pagination-info{ - display: none; -} - -div#aspect_discovery_SimpleSearch_div_search .pagination-links{ - float: left; -} - -table.discovery-filters{ - width: 100%; - background-color: #FFFFFF; -} - -table.discovery-filters tr{ - border-top: 1px solid #EBEBEB; -} -table.discovery-filters td{ - padding: 0; -} - -table.discovery-filters td.selection{ - width: 1%; -} - -table.discovery-filters th.new-filter-header{ - text-align: left; - padding-top: 20px; -} - - -table.discovery-filters td.discovery-filter-input-cell { - padding-left: 3px; -} - - -table.discovery-filters tr.apply-filter{ - background-color: #FAFAFA; -} - -table.discovery-filters tr.apply-filter input{ - width: 65px; - height: 25px; - margin-left: auto; - margin-right: auto; - font-size: 108%; - display: block; - margin-top: 10px; -} - - -table.discovery-filters td.filter-controls{ - width: 50px; -} - -table.discovery-filters input.filter-control { - margin-left: 5px; - text-indent: -1000px; - background-repeat: no-repeat; - background-position: center center; - height: 17px; - width: 17px; - float: left; - background-color: transparent; - border: none; - /*Css props below are required for IE*/ - font-size: 0; - display:block; - line-height: 0; -} - -table.discovery-filters input.filter-control.filter-remove{ - margin-left: 7px; - background-image: url('../../images/button_minus.png'); -} - -table.discovery-filters input.filter-control.filter-add{ - background-image: url('../../images/button_plus.png'); -} - -table.discovery-filters tr.search-filter.filler -{ - background-color: #FAFAFA; - height: 25px; -} - -table.discovery-filters th.new-filter-header -{ - padding-top: 5px; -} - - -.searchTime{ - color: #999999; -} - -h1.ds-div-head{ - font-size: 140%; - padding-bottom: 0px; -} - -#file_news_div_news, -#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser, -#aspect_artifactbrowser_FrontPageSearch_div_front-page-search{ - margin-top: 0; - margin-bottom: 20px; -} - -#ds-user-box{ - float: right; -} diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/yui.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/yui.LICENSE deleted file mode 100644 index 7e24edaf7d4e8126dd1172759287decade45331f..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/css/yui.LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -YUI Library is used under the terms of the BSD License -http://yuilibrary.com/license/ - ---- - -Copyright (c) 2010, Yahoo! Inc. -All rights reserved. - -Redistribution and use of this software 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 Yahoo! Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of Yahoo! Inc. - -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 OWNER 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. \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG.LICENSE deleted file mode 100644 index 9a66484c8fe70779b86ba3e9a7f200eab468475c..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG.LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -DD_belatedPNG Javascript library is used under the terms of the MIT License -http://dillerdesign.com/experiment/DD_belatedPNG/#license - --- - -Copyright (c) 2008 Drew Diller - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG_0.0.8a.js b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG_0.0.8a.js deleted file mode 100644 index 31dd24924c53c790530e62b13f7f60d47790771e..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/DD_belatedPNG_0.0.8a.js +++ /dev/null @@ -1,329 +0,0 @@ -/** -* DD_belatedPNG: Adds IE6 support: PNG images for CSS background-image and HTML <IMG/>. -* Author: Drew Diller -* Email: drew.diller@gmail.com -* URL: http://www.dillerdesign.com/experiment/DD_belatedPNG/ -* Version: 0.0.8a -* Licensed under the MIT License: http://dillerdesign.com/experiment/DD_belatedPNG/#license -* -* Example usage: -* DD_belatedPNG.fix('.png_bg'); // argument is a CSS selector -* DD_belatedPNG.fixPng( someNode ); // argument is an HTMLDomElement -**/ - -/* -PLEASE READ: -Absolutely everything in this script is SILLY. I know this. IE's rendering of certain pixels doesn't make sense, so neither does this code! -*/ - -var DD_belatedPNG = { - ns: 'DD_belatedPNG', - imgSize: {}, - delay: 10, - nodesFixed: 0, - createVmlNameSpace: function () { /* enable VML */ - if (document.namespaces && !document.namespaces[this.ns]) { - document.namespaces.add(this.ns, 'urn:schemas-microsoft-com:vml'); - } - }, - createVmlStyleSheet: function () { /* style VML, enable behaviors */ - /* - Just in case lots of other developers have added - lots of other stylesheets using document.createStyleSheet - and hit the 31-limit mark, let's not use that method! - further reading: http://msdn.microsoft.com/en-us/library/ms531194(VS.85).aspx - */ - var screenStyleSheet, printStyleSheet; - screenStyleSheet = document.createElement('style'); - screenStyleSheet.setAttribute('media', 'screen'); - document.documentElement.firstChild.insertBefore(screenStyleSheet, document.documentElement.firstChild.firstChild); - if (screenStyleSheet.styleSheet) { - screenStyleSheet = screenStyleSheet.styleSheet; - screenStyleSheet.addRule(this.ns + '\\:*', '{behavior:url(#default#VML)}'); - screenStyleSheet.addRule(this.ns + '\\:shape', 'position:absolute;'); - screenStyleSheet.addRule('img.' + this.ns + '_sizeFinder', 'behavior:none; border:none; position:absolute; z-index:-1; top:-10000px; visibility:hidden;'); /* large negative top value for avoiding vertical scrollbars for large images, suggested by James O'Brien, http://www.thanatopsic.org/hendrik/ */ - this.screenStyleSheet = screenStyleSheet; - - /* Add a print-media stylesheet, for preventing VML artifacts from showing up in print (including preview). */ - /* Thanks to R�mi Pr�vost for automating this! */ - printStyleSheet = document.createElement('style'); - printStyleSheet.setAttribute('media', 'print'); - document.documentElement.firstChild.insertBefore(printStyleSheet, document.documentElement.firstChild.firstChild); - printStyleSheet = printStyleSheet.styleSheet; - printStyleSheet.addRule(this.ns + '\\:*', '{display: none !important;}'); - printStyleSheet.addRule('img.' + this.ns + '_sizeFinder', '{display: none !important;}'); - } - }, - readPropertyChange: function () { - var el, display, v; - el = event.srcElement; - if (!el.vmlInitiated) { - return; - } - if (event.propertyName.search('background') != -1 || event.propertyName.search('border') != -1) { - DD_belatedPNG.applyVML(el); - } - if (event.propertyName == 'style.display') { - display = (el.currentStyle.display == 'none') ? 'none' : 'block'; - for (v in el.vml) { - if (el.vml.hasOwnProperty(v)) { - el.vml[v].shape.style.display = display; - } - } - } - if (event.propertyName.search('filter') != -1) { - DD_belatedPNG.vmlOpacity(el); - } - }, - vmlOpacity: function (el) { - if (el.currentStyle.filter.search('lpha') != -1) { - var trans = el.currentStyle.filter; - trans = parseInt(trans.substring(trans.lastIndexOf('=')+1, trans.lastIndexOf(')')), 10)/100; - el.vml.color.shape.style.filter = el.currentStyle.filter; /* complete guesswork */ - el.vml.image.fill.opacity = trans; /* complete guesswork */ - } - }, - handlePseudoHover: function (el) { - setTimeout(function () { /* wouldn't work as intended without setTimeout */ - DD_belatedPNG.applyVML(el); - }, 1); - }, - /** - * This is the method to use in a document. - * @param {String} selector - REQUIRED - a CSS selector, such as '#doc .container' - **/ - fix: function (selector) { - if (this.screenStyleSheet) { - var selectors, i; - selectors = selector.split(','); /* multiple selectors supported, no need for multiple calls to this anymore */ - for (i=0; i<selectors.length; i++) { - this.screenStyleSheet.addRule(selectors[i], 'behavior:expression(DD_belatedPNG.fixPng(this))'); /* seems to execute the function without adding it to the stylesheet - interesting... */ - } - } - }, - applyVML: function (el) { - el.runtimeStyle.cssText = ''; - this.vmlFill(el); - this.vmlOffsets(el); - this.vmlOpacity(el); - if (el.isImg) { - this.copyImageBorders(el); - } - }, - attachHandlers: function (el) { - var self, handlers, handler, moreForAs, a, h; - self = this; - handlers = {resize: 'vmlOffsets', move: 'vmlOffsets'}; - if (el.nodeName == 'A') { - moreForAs = {mouseleave: 'handlePseudoHover', mouseenter: 'handlePseudoHover', focus: 'handlePseudoHover', blur: 'handlePseudoHover'}; - for (a in moreForAs) { - if (moreForAs.hasOwnProperty(a)) { - handlers[a] = moreForAs[a]; - } - } - } - for (h in handlers) { - if (handlers.hasOwnProperty(h)) { - handler = function () { - self[handlers[h]](el); - }; - el.attachEvent('on' + h, handler); - } - } - el.attachEvent('onpropertychange', this.readPropertyChange); - }, - giveLayout: function (el) { - el.style.zoom = 1; - if (el.currentStyle.position == 'static') { - el.style.position = 'relative'; - } - }, - copyImageBorders: function (el) { - var styles, s; - styles = {'borderStyle':true, 'borderWidth':true, 'borderColor':true}; - for (s in styles) { - if (styles.hasOwnProperty(s)) { - el.vml.color.shape.style[s] = el.currentStyle[s]; - } - } - }, - vmlFill: function (el) { - if (!el.currentStyle) { - return; - } else { - var elStyle, noImg, lib, v, img, imgLoaded; - elStyle = el.currentStyle; - } - for (v in el.vml) { - if (el.vml.hasOwnProperty(v)) { - el.vml[v].shape.style.zIndex = elStyle.zIndex; - } - } - el.runtimeStyle.backgroundColor = ''; - el.runtimeStyle.backgroundImage = ''; - noImg = true; - if (elStyle.backgroundImage != 'none' || el.isImg) { - if (!el.isImg) { - el.vmlBg = elStyle.backgroundImage; - el.vmlBg = el.vmlBg.substr(5, el.vmlBg.lastIndexOf('")')-5); - } - else { - el.vmlBg = el.src; - } - lib = this; - if (!lib.imgSize[el.vmlBg]) { /* determine size of loaded image */ - img = document.createElement('img'); - lib.imgSize[el.vmlBg] = img; - img.className = lib.ns + '_sizeFinder'; - img.runtimeStyle.cssText = 'behavior:none; position:absolute; left:-10000px; top:-10000px; border:none; margin:0; padding:0;'; /* make sure to set behavior to none to prevent accidental matching of the helper elements! */ - imgLoaded = function () { - this.width = this.offsetWidth; /* weird cache-busting requirement! */ - this.height = this.offsetHeight; - lib.vmlOffsets(el); - }; - img.attachEvent('onload', imgLoaded); - img.src = el.vmlBg; - img.removeAttribute('width'); - img.removeAttribute('height'); - document.body.insertBefore(img, document.body.firstChild); - } - el.vml.image.fill.src = el.vmlBg; - noImg = false; - } - el.vml.image.fill.on = !noImg; - el.vml.image.fill.color = 'none'; - el.vml.color.shape.style.backgroundColor = elStyle.backgroundColor; - el.runtimeStyle.backgroundImage = 'none'; - el.runtimeStyle.backgroundColor = 'transparent'; - }, - /* IE can't figure out what do when the offsetLeft and the clientLeft add up to 1, and the VML ends up getting fuzzy... so we have to push/enlarge things by 1 pixel and then clip off the excess */ - vmlOffsets: function (el) { - var thisStyle, size, fudge, makeVisible, bg, bgR, dC, altC, b, c, v; - thisStyle = el.currentStyle; - size = {'W':el.clientWidth+1, 'H':el.clientHeight+1, 'w':this.imgSize[el.vmlBg].width, 'h':this.imgSize[el.vmlBg].height, 'L':el.offsetLeft, 'T':el.offsetTop, 'bLW':el.clientLeft, 'bTW':el.clientTop}; - fudge = (size.L + size.bLW == 1) ? 1 : 0; - /* vml shape, left, top, width, height, origin */ - makeVisible = function (vml, l, t, w, h, o) { - vml.coordsize = w+','+h; - vml.coordorigin = o+','+o; - vml.path = 'm0,0l'+w+',0l'+w+','+h+'l0,'+h+' xe'; - vml.style.width = w + 'px'; - vml.style.height = h + 'px'; - vml.style.left = l + 'px'; - vml.style.top = t + 'px'; - }; - makeVisible(el.vml.color.shape, (size.L + (el.isImg ? 0 : size.bLW)), (size.T + (el.isImg ? 0 : size.bTW)), (size.W-1), (size.H-1), 0); - makeVisible(el.vml.image.shape, (size.L + size.bLW), (size.T + size.bTW), (size.W), (size.H), 1 ); - bg = {'X':0, 'Y':0}; - if (el.isImg) { - bg.X = parseInt(thisStyle.paddingLeft, 10) + 1; - bg.Y = parseInt(thisStyle.paddingTop, 10) + 1; - } - else { - for (b in bg) { - if (bg.hasOwnProperty(b)) { - this.figurePercentage(bg, size, b, thisStyle['backgroundPosition'+b]); - } - } - } - el.vml.image.fill.position = (bg.X/size.W) + ',' + (bg.Y/size.H); - bgR = thisStyle.backgroundRepeat; - dC = {'T':1, 'R':size.W+fudge, 'B':size.H, 'L':1+fudge}; /* these are defaults for repeat of any kind */ - altC = { 'X': {'b1': 'L', 'b2': 'R', 'd': 'W'}, 'Y': {'b1': 'T', 'b2': 'B', 'd': 'H'} }; - if (bgR != 'repeat' || el.isImg) { - c = {'T':(bg.Y), 'R':(bg.X+size.w), 'B':(bg.Y+size.h), 'L':(bg.X)}; /* these are defaults for no-repeat - clips down to the image location */ - if (bgR.search('repeat-') != -1) { /* now let's revert to dC for repeat-x or repeat-y */ - v = bgR.split('repeat-')[1].toUpperCase(); - c[altC[v].b1] = 1; - c[altC[v].b2] = size[altC[v].d]; - } - if (c.B > size.H) { - c.B = size.H; - } - el.vml.image.shape.style.clip = 'rect('+c.T+'px '+(c.R+fudge)+'px '+c.B+'px '+(c.L+fudge)+'px)'; - } - else { - el.vml.image.shape.style.clip = 'rect('+dC.T+'px '+dC.R+'px '+dC.B+'px '+dC.L+'px)'; - } - }, - figurePercentage: function (bg, size, axis, position) { - var horizontal, fraction; - fraction = true; - horizontal = (axis == 'X'); - switch(position) { - case 'left': - case 'top': - bg[axis] = 0; - break; - case 'center': - bg[axis] = 0.5; - break; - case 'right': - case 'bottom': - bg[axis] = 1; - break; - default: - if (position.search('%') != -1) { - bg[axis] = parseInt(position, 10) / 100; - } - else { - fraction = false; - } - } - bg[axis] = Math.ceil( fraction ? ( (size[horizontal?'W': 'H'] * bg[axis]) - (size[horizontal?'w': 'h'] * bg[axis]) ) : parseInt(position, 10) ); - if (bg[axis] % 2 === 0) { - bg[axis]++; - } - return bg[axis]; - }, - fixPng: function (el) { - el.style.behavior = 'none'; - var lib, els, nodeStr, v, e; - if (el.nodeName == 'BODY' || el.nodeName == 'TD' || el.nodeName == 'TR') { /* elements not supported yet */ - return; - } - el.isImg = false; - if (el.nodeName == 'IMG') { - if(el.src.toLowerCase().search(/\.png(\?\d+)?$/) != -1) { - el.isImg = true; - el.style.visibility = 'hidden'; - } - else { - return; - } - } - else if (el.currentStyle.backgroundImage.toLowerCase().search('.png') == -1) { - return; - } - lib = DD_belatedPNG; - el.vml = {color: {}, image: {}}; - els = {shape: {}, fill: {}}; - for (v in el.vml) { - if (el.vml.hasOwnProperty(v)) { - for (e in els) { - if (els.hasOwnProperty(e)) { - nodeStr = lib.ns + ':' + e; - el.vml[v][e] = document.createElement(nodeStr); - } - } - el.vml[v].shape.stroked = false; - el.vml[v].shape.appendChild(el.vml[v].fill); - el.parentNode.insertBefore(el.vml[v].shape, el); - } - } - el.vml.image.shape.fillcolor = 'none'; /* Don't show blank white shapeangle when waiting for image to load. */ - /* If the height and width attributes are set, then scale to size, if not, display as per usual */ - if (el.height && el.width){el.vml.image.fill.type = 'frame';} else {el.vml.image.fill.type = 'tile';} - el.vml.color.fill.on = false; /* Actually going to apply vml element's style.backgroundColor, so hide the whiteness. */ - lib.attachHandlers(el); - lib.giveLayout(el); - lib.giveLayout(el.offsetParent); - el.vmlInitiated = true; - lib.applyVML(el); /* Render! */ - } -}; -try { - document.execCommand("BackgroundImageCache", false, true); /* TredoSoft Multiple IE doesn't like this, so try{} it */ -} catch(r) {} -DD_belatedPNG.createVmlNameSpace(); -DD_belatedPNG.createVmlStyleSheet(); \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/choice-support.js b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/choice-support.js deleted file mode 100644 index dae4db539422e0c2de7b71f4718ee18be72349fa..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/choice-support.js +++ /dev/null @@ -1,562 +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/ - */ -// Client-side scripting to support DSpace Choice Control - -// IMPORTANT NOTE: -// This version of choice-support.js has been rewritten to use jQuery -// instead of prototype & scriptaculous. The goal was not to change the -// way it works in any way, just to get the prototype dependency out. -// @Author Art Lowel (art.lowel at atmire.com) - -// Entry points: -// 1. DSpaceAutocomplete -- add autocomplete (suggest) to an input field -// -// 2. DSpaceChoiceLookup -- create popup window with authority choices -// -// @Author: Larry Stone <lcs@hulmail.harvard.edu> -// $Revision $ - -// -------------------- support for Autocomplete (Suggest) - -// Autocomplete utility: -// Arguments: -// formID -- ID attribute of form tag -// args properties: -// metadataField -- metadata field e.g. dc_contributor_author -// inputName -- input field name for text input, or base of "Name" pair -// authorityName -- input field name in which to set authority -// containerID -- ID attribute of DIV to hold the menu objects -// indicatorID -- ID attribute of element to use as a "loading" indicator -// confidenceIndicatorID -- ID of element on which to set confidence -// confidenceName - NAME of confidence input (not ID) -// contextPath -- URL path prefix (i.e. webapp contextPath) for DSpace. -// collection -- db ID of dspace collection to serve as context -// isClosed -- true if authority value is required, false = non-auth allowed -// XXX Can't really enforce "isClosed=true" with autocomplete, user can type anything -// -// NOTE: Successful autocomplete always sets confidence to 'accepted' since -// authority value (if any) *was* chosen interactively by a human. -function DSpaceSetupAutocomplete(formID, args) { - - $(function() { - if (args.authorityName == null) - args.authorityName = dspace_makeFieldInput(args.inputName, '_authority'); - var form = $('#' + formID)[0]; - var inputID = form.elements[args.inputName].id; - - var authorityID = null; - if (form.elements[args.authorityName] != null) - authorityID = form.elements[args.authorityName].id; - - // AJAX menu source, can add &query=TEXT - var choiceURL = args.contextPath + "/choices/" + args.metadataField; - var collID = args.collection == null ? -1 : args.collection; - choiceURL += '?collection=' + collID; - - var ac = $('#' + inputID); - ac.autocomplete({ - source: function(request, response) { - var reqUrl = choiceURL; - if(request && request.term) { - reqUrl += "&query=" + request.term; - } - $.get(reqUrl, function(xmldata) { - var options = []; - var authorities = []; - $(xmldata).find('Choice').each(function() { - // get value - var value = $(this).attr('value') ? $(this).attr('value') : null; - // get label, if empty set it to value - var label = $(this).text() ? $(this).text() : value; - // if value was empty but label was provided, set value to label - if(!value) { - value = label; - } - // if at this point either value or label == null, this means none of both were set and we shouldn't add it to the list of options - if (label != null) { - options.push({ - label: label, - value: value - }); - authorities['label: ' + label + ', value: ' + value] = $(this).attr('authority') ? $(this).attr('authority') : value; - } - }); - ac.data('authorities',authorities); - response(options); - }); - }, - select: function(event, ui) { - // NOTE: lookup element late because it might not be in DOM - // at the time we evaluate the function.. -// var authInput = document.getElementById(authorityID); -// var authValue = li == null ? "" : li.getAttribute("authority"); - var authInput = $('#' + authorityID); - if(authInput.length > 0) { - authInput = authInput[0]; - } - else { - authInput = null; - } - var authorities = ac.data('authorities'); - var authValue = authorities['label: ' + ui.item.label + ', value: ' + ui.item.value]; - if (authInput != null) { - authInput.value = authValue; - // update confidence input's value too if available. - if (args.confidenceName != null) { - var confInput = authInput.form.elements[args.confidenceName]; - if (confInput != null) - confInput.value = 'accepted'; - } - } - // make indicator blank if no authority value - DSpaceUpdateConfidence(document, args.confidenceIndicatorID, - authValue == null || authValue == '' ? 'blank' : 'accepted'); - } - }); - }); -} - -// -------------------- support for Lookup Popup - -// Create popup window with authority choices for value of an input field. -// This is intended to be called by onClick of a "Lookup" or "Add" button. -function DSpaceChoiceLookup(url, field, formID, valueInput, authInput, - confIndicatorID, collectionID, isName, isRepeating) { - // fill in parameters for URL of popup window - url += '?field=' + field + '&formID=' + formID + '&valueInput=' + valueInput + - '&authorityInput=' + authInput + '&collection=' + collectionID + - '&isName=' + isName + '&isRepeating=' + isRepeating + '&confIndicatorID=' + confIndicatorID + - '&limit=50'; //limit to 50 results at once (make configurable?) - - // primary input field - for positioning popup. - var inputFieldName = isName ? dspace_makeFieldInput(valueInput, '_last') : valueInput; - var inputField = $('input[name = ' + inputFieldName + ']'); - // sometimes a textarea is used, in which case the previous jQuery search delivered no results... - if(inputField.length == 0) { - // so search for a textarea - inputField = $('textarea[name = ' + inputFieldName + ']'); - } - var cOffset = 0; - if (inputField != null) - cOffset = inputField.offset(); - var width = 600; // XXX guesses! these should be params, or configured.. - var height = 470; - var left; - var top; - if (window.screenX == null) { - left = window.screenLeft + cOffset.left - (width / 2); - top = window.screenTop + cOffset.top - (height / 2); - } else { - left = window.screenX + cOffset.left - (width / 2); - top = window.screenY + cOffset.top - (height / 2); - } - if (left < 0) left = 0; - if (top < 0) top = 0; - var pw = window.open(url, 'ignoreme', - 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + - ',toolbar=no,menubar=no,location=no,status=no,resizable'); - if (window.focus) pw.focus(); - return false; -} - -// Run this as the Lookup page is loaded to initialize DOM objects, load choices -function DSpaceChoicesSetup(form) { - // find the "LEGEND" in fieldset, which acts as page title, - var legend = $('#aspect_general_ChoiceLookupTransformer_list_choicesList :header:first'); - //save the template as a jQuery data field - legend.data('template', legend.html()); - legend.html("Loading..."); - DSpaceChoicesLoad(form); -} - - -// Populate the "select" (in popup window) with options from ajax request -// stash some parameters as properties of the "select" so we can add to -// the last start index to query for next set of results. -function DSpaceChoicesLoad(form) { - var field = $('*[name = paramField]').val(); - var value = $('*[name = paramValue]').val(); - if (!value) - value = ''; - var start = $('*[name = paramStart]').val(); - var limit = $('*[name = paramLimit]').val(); - var formID = $('*[name = paramFormID]').val(); - var collID = $('*[name = paramCollection]').val(); - var isName = $('*[name = paramIsName]').val() == 'true'; - var isRepeating = $('*[name = paramIsRepeating]').val() == 'true'; - var isClosed = $('*[name = paramIsClosed]').val() == 'true'; - var contextPath = $('*[name = contextPath]').val(); - var fail = $('*[name = paramFail]').val(); - var valueInput = $('*[name = paramValueInput]').val(); - var nonAuthority = ""; - var pNAInput = $('*[name = paramNonAuthority]'); - if (pNAInput.length > 0) - nonAuthority = pNAInput.val(); - - // get value from form inputs in opener if not explicitly supplied - if (value.length == 0) { - // This bit of javascript is accessing the form that opened the popup window, - // so that we can grab the value the user entered before pressing the "Lookup & Add" button - var of = $(window.opener.document).find('#' + formID); - if (isName) - value = makePersonName(of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_last') + ']').val(), - of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_first') + ']').val()); - else - value = of.find('*[name = ' + valueInput + ']').val(); - - // if this is a repeating input, clear the source value so that e.g. - // clicking "Next" on a submit-describe page will not *add* the proposed - // lookup text as a metadata value: - if (isRepeating) { - if (isName) { - of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_last') + ']').val(''); - of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_first') + ']').val(''); - } - else - of.find('*[name = ' + valueInput + ']').val(null); - } - - // Save passed-in value to hidden 'paramValue' field in the popup window - // (This will allow the user to get "more results" for the same query, - // if results are on more than one page.) - $('*[name = paramValue]').val(value); - } - - // start spinner - var indicator = $('#lookup_indicator_id'); - indicator.show('fast'); - - $(window).ajaxError(function(e, xhr, settings, exception) { - window.alert(fail + " Exception=" + e); - if (indicator != null) indicator.style.display = "none"; - }); - - // AJAX to send off the query to the "/choices" URL, and - // then parse the response based on whether it was successful or error occurred - // NOTE: you can send this same query manually to see result sample. - // Just enter the URL & pass all data values on query string. - $.ajax({ - url: contextPath + "/choices/" + field, - type: "GET", - data: {query: value, collection: collID, - start: start, limit: limit}, - error: function() { - window.alert(fail + " HTTP error resonse"); - if (indicator != null) indicator.style.display = "none"; - }, - success: function(data) { - var Choices = $(data).find('Choices'); - var err = Choices.attr('error'); - if (err != null && err == 'true') - window.alert(fail + " Server indicates error in response."); - var opts = Choices.find('Choice'); - - // update range message and update 'more' button - var oldStart = 1 * Choices.attr('start'); - var nextStart = oldStart + opts.length; - var lastTotal = Choices.attr('total'); - var resultMore = Choices.attr('more'); - //if no more results to display, then disable the "more" button - if(resultMore==null || resultMore == 'false') - $('*[name = more]').attr('disabled', 'true'); - else //otherwise, enable the "more" button - $('*[name = more]').removeAttr('disabled'); - // save next starting index to hidden field - $('*[name = paramStart]').val(nextStart); - - // clear select first - var select = $('select[name = chooser]:first'); - select.find('option:not(:last)').remove(); - var lastOption = select.find('option:last'); - - var selectedByValue = -1; // select by value match - var selectedByChoices = -1; // Choice says its selected - $.each(opts, function(index) { -// debugger; - var current = $(this); - if (current.attr('value') == value) - selectedByValue = index; - if(current.attr('selected') != undefined) - selectedByChoices = index; - - var newOption = $('<option value="' + current.attr('value') + '">' + current.text() + '</option>'); - newOption.data('authority', current.attr('authority')); - - if (lastOption.length > 0) - lastOption.insertBefore(newOption); - else - select.append(newOption); - }); - - - // add non-authority option if needed. - if (!isClosed) { - select.append(new Option(dspace_formatMessage(nonAuthority, value), value), null); - } - var defaultSelected = -1; - if (selectedByChoices >= 0) - defaultSelected = selectedByChoices; - else if (selectedByValue >= 0) - defaultSelected = selectedByValue; - else if (select[0].options.length == 1) - defaultSelected = 0; - - // load default-selected value - if (defaultSelected >= 0) { - select[0].options[defaultSelected].defaultSelected = true; - var so = select[0].options[defaultSelected]; - if (isName) { - $('*[name = text1]').val(lastNameOf(so.value)); - $('*[name = text2]').val(firstNameOf(so.value)); - } - else - $('*[name = text1]').val(so.value); - } - - // turn off spinner - indicator.hide('fast'); - - //If no results, make sure to display "0 to 0 of 0" - var startNum = (nextStart==0 ? 0 : oldStart+1); - //Fill out the counter values in the "Results x to y of z" line - var legend = $('#aspect_general_ChoiceLookupTransformer_list_choicesList :header:first'); - legend.html(dspace_formatMessage(legend.data('template'), - startNum, nextStart, lastTotal, value)); - } - }); -} - -// handler for change event on choice selector - load new values -function DSpaceChoicesSelectOnChange() { - // "this" is the window, - - var form = $('#aspect_general_ChoiceLookupTransformer_div_lookup'); - var select = form.find('*[name = chooser]'); - - var isName = form.find('*[name = paramIsName]').val() == 'true'; - - var selectedValue = select.val(); - - if (isName) { - form.find('*[name = text1]').val(lastNameOf(selectedValue)); - form.find('*[name = text2]').val(firstNameOf(selectedValue)); - } - else - form.find('*[name = text1]').val(selectedValue); -} - -// handler for lookup popup's accept (or add) button -// stuff values back to calling page, force an add if necessary, and close. -function DSpaceChoicesAcceptOnClick() { - var select = $('*[name = chooser]'); - var isName = $('*[name = paramIsName]').val() == 'true'; - var isRepeating = $('*[name = paramIsRepeating]').val() == 'true'; - var valueInput = $('*[name = paramValueInput]').val(); - var authorityInput = $('*[name = paramAuthorityInput]').val(); - var formID = $('*[name = paramFormID]').val(); - var confIndicatorID = $('*[name = paramConfIndicatorID]').length = 0 ? null : $('*[name = paramConfIndicatorID]').val(); - - // default the authority input if not supplied. - if (authorityInput.length == 0) - authorityInput = dspace_makeFieldInput(valueInput, '_authority'); - - // always stuff text fields back into caller's value input(s) - if (valueInput.length > 0) { - var of = $(window.opener.document).find('#' + formID); - if (isName) { - of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_last') + ']').val($('*[name = text1]').val()); - of.find('*[name = ' + dspace_makeFieldInput(valueInput, '_first') + ']').val($('*[name = text2]').val()); - } - else - of.find('*[name = ' + valueInput + ']').val($('*[name = text1]').val()); - - if (authorityInput.length > 0 && of.find('*[name = ' + authorityInput + ']').length > 0) { - // conf input is auth input, substitute '_confidence' for '_authority' - // if conf fieldname is FIELD_confidence_NUMBER, then '_authority_' => '_confidence_' - var confInput = ""; - - var ci = authorityInput.lastIndexOf("_authority_"); - if (ci < 0) - confInput = authorityInput.substring(0, authorityInput.length - 10) + '_confidence'; - else - confInput = authorityInput.substring(0, ci) + "_confidence_" + authorityInput.substring(ci + 11); - // DEBUG: - // window.alert('Setting fields auth="'+authorityInput+'", conf="'+confInput+'"'); - - var authValue = null; - var selectedOption = select.find(':selected'); - if (selectedOption.length >= 0 && selectedOption.data('authority') != null) { - of.find('*[name = ' + authorityInput + ']').val(selectedOption.data('authority')); - } - of.find('*[name = ' + confInput + ']').val('accepted'); - // make indicator blank if no authority value - DSpaceUpdateConfidence(window.opener.document, confIndicatorID, - authValue == null || authValue == '' ? 'blank' : 'accepted'); - } - - // force the submit button -- if there is an "add" - if (isRepeating) { - var add = of.find('*[name = submit_' + valueInput + '_add]'); - if (add.length > 0) - add.click(); - else - alert('Sanity check: Cannot find button named "submit_' + valueInput + '_add"'); - } - } - window.close(); - return false; -} - -// handler for lookup popup's more button -function DSpaceChoicesMoreOnClick() { - //reload the window -- this should return the next results set - location.reload(); -} - -// handler for lookup popup's cancel button -function DSpaceChoicesCancelOnClick() { - window.close(); - return false; -} - -// -------------------- Utilities - -// DSpace person-name conventions, see DCPersonName -function makePersonName(lastName, firstName) { - return (firstName == null || firstName.length == 0) ? lastName : - lastName + ", " + firstName; -} - -// DSpace person-name conventions, see DCPersonName -function firstNameOf(personName) { - var comma = personName.indexOf(","); - return (comma < 0) ? "" : stringTrim(personName.substring(comma + 1)); -} - -// DSpace person-name conventions, see DCPersonName -function lastNameOf(personName) { - var comma = personName.indexOf(","); - return stringTrim((comma < 0) ? personName : personName.substring(0, comma)); -} - -// replicate java String.trim() -function stringTrim(str) { - var start = 0; - var end = str.length; - for (; str.charAt(start) == ' ' && start < end; ++start) ; - for (; end > start && str.charAt(end - 1) == ' '; --end) ; - return str.slice(start, end); -} - -// format utility - replace @1@, @2@ etc with args 1, 2, 3.. -// NOTE params MUST be monotonically increasing -// NOTE we can't use "{1}" like the i18n catalog because it elides them!! -// ...UNLESS maybe it were to be fixed not to when no params... -function dspace_formatMessage() { - var template = dspace_formatMessage.arguments[0]; - var i; - for (i = 1; i < arguments.length; ++i) { - var pattern = '@' + i + '@'; - if (template.search(pattern) >= 0) - { - var value = dspace_formatMessage.arguments[i]; - if (value == undefined) - value = ''; - template = template.replace(pattern, value); - } - } - return template; -} - -// utility to make sub-field name of input field, e.g. _last, _first, _auth.. -// if name ends with _1, _2 etc, put sub-name BEFORE the number -function dspace_makeFieldInput(name, sub) { - var i = name.search("_[0-9]+$"); - if (i < 0) - return name + sub; - else - return name.substr(0, i) + sub + name.substr(i); -} - -// update the class value of confidence-indicating element -function DSpaceUpdateConfidence(doc, confIndicatorID, newValue) { - // sanity checks - need valid ID and a real DOM object - if (confIndicatorID == null || confIndicatorID == "") - return; - var confElt = doc.getElementById(confIndicatorID); - if (confElt == null) - return; - - // add or update CSS class with new confidence value, e.g. "cf-accepted". - if (confElt.className == null) - confElt.className = "cf-" + newValue; - else { - var classes = confElt.className.split(" "); - var newClasses = ""; - var found = false; - for (var i = 0; i < classes.length; ++i) { - if (classes[i].match('^cf-[a-zA-Z0-9]+$')) { - newClasses += "cf-" + newValue + " "; - found = true; - } - else - newClasses += classes[i] + " "; - } - if (!found) - newClasses += "cf-" + newValue + " "; - confElt.className = newClasses; - } -} - -// respond to "onchanged" event on authority input field -// set confidence to 'accepted' if authority was changed by user. -function DSpaceAuthorityOnChange(self, confValueID, confIndicatorID) { - var confidence = 'accepted'; - if (confValueID != null && confValueID != '') { - var confValueField = document.getElementById(confValueID); - if (confValueField != null) - confValueField.value = confidence; - } - DSpaceUpdateConfidence(document, confIndicatorID, confidence); - return false; -} - -// respond to click on the authority-value lock button in Edit Item Metadata: -// "button" is bound to the image input for the lock button, "this" -function DSpaceToggleAuthorityLock(button, authInputID) { - // sanity checks - need valid ID and a real DOM object - if (authInputID == null || authInputID == '') - return false; - var authInput = document.getElementById(authInputID); - if (authInput == null) - return false; - - // look for is-locked or is-unlocked in class list: - var classes = button.className.split(' '); - var newClass = ''; - var newLocked = false; - var found = false; - for (var i = 0; i < classes.length; ++i) { - if (classes[i] == 'is-locked') { - newLocked = false; - found = true; - } - else if (classes[i] == 'is-unlocked') { - newLocked = true; - found = true; - } - else - newClass += classes[i] + ' '; - } - if (!found) - return false; - // toggle the image, and set readability - button.className = newClass + (newLocked ? 'is-locked' : 'is-unlocked') + ' '; - authInput.readOnly = newLocked; - return false; -} diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui-1.8.15.custom.min.js b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui-1.8.15.custom.min.js deleted file mode 100644 index fbcceae8c3f31132a610eae01bfe702885f5e1d0..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui-1.8.15.custom.min.js +++ /dev/null @@ -1,790 +0,0 @@ -/*! - * jQuery UI 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI - */ -(function(c,j){function k(a,b){var d=a.nodeName.toLowerCase();if("area"===d){b=a.parentNode;d=b.name;if(!a.href||!d||b.nodeName.toLowerCase()!=="map")return false;a=c("img[usemap=#"+d+"]")[0];return!!a&&l(a)}return(/input|select|textarea|button|object/.test(d)?!a.disabled:"a"==d?a.href||b:b)&&l(a)}function l(a){return!c(a).parents().andSelf().filter(function(){return c.curCSS(this,"visibility")==="hidden"||c.expr.filters.hidden(this)}).length}c.ui=c.ui||{};if(!c.ui.version){c.extend(c.ui,{version:"1.8.15", -keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}});c.fn.extend({propAttr:c.fn.prop||c.fn.attr,_focus:c.fn.focus,focus:function(a,b){return typeof a==="number"?this.each(function(){var d= -this;setTimeout(function(){c(d).focus();b&&b.call(d)},a)}):this._focus.apply(this,arguments)},scrollParent:function(){var a;a=c.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(c.curCSS(this,"position",1))&&/(auto|scroll)/.test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(c.curCSS(this, -"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0);return/fixed/.test(this.css("position"))||!a.length?c(document):a},zIndex:function(a){if(a!==j)return this.css("zIndex",a);if(this.length){a=c(this[0]);for(var b;a.length&&a[0]!==document;){b=a.css("position");if(b==="absolute"||b==="relative"||b==="fixed"){b=parseInt(a.css("zIndex"),10);if(!isNaN(b)&&b!==0)return b}a=a.parent()}}return 0},disableSelection:function(){return this.bind((c.support.selectstart?"selectstart": -"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}});c.each(["Width","Height"],function(a,b){function d(f,g,m,n){c.each(e,function(){g-=parseFloat(c.curCSS(f,"padding"+this,true))||0;if(m)g-=parseFloat(c.curCSS(f,"border"+this+"Width",true))||0;if(n)g-=parseFloat(c.curCSS(f,"margin"+this,true))||0});return g}var e=b==="Width"?["Left","Right"]:["Top","Bottom"],h=b.toLowerCase(),i={innerWidth:c.fn.innerWidth,innerHeight:c.fn.innerHeight, -outerWidth:c.fn.outerWidth,outerHeight:c.fn.outerHeight};c.fn["inner"+b]=function(f){if(f===j)return i["inner"+b].call(this);return this.each(function(){c(this).css(h,d(this,f)+"px")})};c.fn["outer"+b]=function(f,g){if(typeof f!=="number")return i["outer"+b].call(this,f);return this.each(function(){c(this).css(h,d(this,f,true,g)+"px")})}});c.extend(c.expr[":"],{data:function(a,b,d){return!!c.data(a,d[3])},focusable:function(a){return k(a,!isNaN(c.attr(a,"tabindex")))},tabbable:function(a){var b=c.attr(a, -"tabindex"),d=isNaN(b);return(d||b>=0)&&k(a,!d)}});c(function(){var a=document.body,b=a.appendChild(b=document.createElement("div"));c.extend(b.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0});c.support.minHeight=b.offsetHeight===100;c.support.selectstart="onselectstart"in b;a.removeChild(b).style.display="none"});c.extend(c.ui,{plugin:{add:function(a,b,d){a=c.ui[a].prototype;for(var e in d){a.plugins[e]=a.plugins[e]||[];a.plugins[e].push([b,d[e]])}},call:function(a,b,d){if((b=a.plugins[b])&& -a.element[0].parentNode)for(var e=0;e<b.length;e++)a.options[b[e][0]]&&b[e][1].apply(a.element,d)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(a,b){if(c(a).css("overflow")==="hidden")return false;b=b&&b==="left"?"scrollLeft":"scrollTop";var d=false;if(a[b]>0)return true;a[b]=1;d=a[b]>0;a[b]=0;return d},isOverAxis:function(a,b,d){return a>b&&a<b+d},isOver:function(a,b,d,e,h,i){return c.ui.isOverAxis(a,d,h)&& -c.ui.isOverAxis(b,e,i)}})}})(jQuery); -;/*! - * jQuery UI Widget 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Widget - */ -(function(b,j){if(b.cleanData){var k=b.cleanData;b.cleanData=function(a){for(var c=0,d;(d=a[c])!=null;c++)b(d).triggerHandler("remove");k(a)}}else{var l=b.fn.remove;b.fn.remove=function(a,c){return this.each(function(){if(!c)if(!a||b.filter(a,[this]).length)b("*",this).add([this]).each(function(){b(this).triggerHandler("remove")});return l.call(b(this),a,c)})}}b.widget=function(a,c,d){var e=a.split(".")[0],f;a=a.split(".")[1];f=e+"-"+a;if(!d){d=c;c=b.Widget}b.expr[":"][f]=function(h){return!!b.data(h, -a)};b[e]=b[e]||{};b[e][a]=function(h,g){arguments.length&&this._createWidget(h,g)};c=new c;c.options=b.extend(true,{},c.options);b[e][a].prototype=b.extend(true,c,{namespace:e,widgetName:a,widgetEventPrefix:b[e][a].prototype.widgetEventPrefix||a,widgetBaseClass:f},d);b.widget.bridge(a,b[e][a])};b.widget.bridge=function(a,c){b.fn[a]=function(d){var e=typeof d==="string",f=Array.prototype.slice.call(arguments,1),h=this;d=!e&&f.length?b.extend.apply(null,[true,d].concat(f)):d;if(e&&d.charAt(0)==="_")return h; -e?this.each(function(){var g=b.data(this,a),i=g&&b.isFunction(g[d])?g[d].apply(g,f):g;if(i!==g&&i!==j){h=i;return false}}):this.each(function(){var g=b.data(this,a);g?g.option(d||{})._init():b.data(this,a,new c(d,this))});return h}};b.Widget=function(a,c){arguments.length&&this._createWidget(a,c)};b.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:false},_createWidget:function(a,c){b.data(c,this.widgetName,this);this.element=b(c);this.options=b.extend(true,{},this.options, -this._getCreateOptions(),a);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()});this._create();this._trigger("create");this._init()},_getCreateOptions:function(){return b.metadata&&b.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName);this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled ui-state-disabled")}, -widget:function(){return this.element},option:function(a,c){var d=a;if(arguments.length===0)return b.extend({},this.options);if(typeof a==="string"){if(c===j)return this.options[a];d={};d[a]=c}this._setOptions(d);return this},_setOptions:function(a){var c=this;b.each(a,function(d,e){c._setOption(d,e)});return this},_setOption:function(a,c){this.options[a]=c;if(a==="disabled")this.widget()[c?"addClass":"removeClass"](this.widgetBaseClass+"-disabled ui-state-disabled").attr("aria-disabled",c);return this}, -enable:function(){return this._setOption("disabled",false)},disable:function(){return this._setOption("disabled",true)},_trigger:function(a,c,d){var e=this.options[a];c=b.Event(c);c.type=(a===this.widgetEventPrefix?a:this.widgetEventPrefix+a).toLowerCase();d=d||{};if(c.originalEvent){a=b.event.props.length;for(var f;a;){f=b.event.props[--a];c[f]=c.originalEvent[f]}}this.element.trigger(c,d);return!(b.isFunction(e)&&e.call(this.element[0],c,d)===false||c.isDefaultPrevented())}}})(jQuery); -;/*! - * jQuery UI Mouse 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Mouse - * - * Depends: - * jquery.ui.widget.js - */ -(function(b){b.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var a=this;this.element.bind("mousedown."+this.widgetName,function(c){return a._mouseDown(c)}).bind("click."+this.widgetName,function(c){if(true===b.data(c.target,a.widgetName+".preventClickEvent")){b.removeData(c.target,a.widgetName+".preventClickEvent");c.stopImmediatePropagation();return false}});this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName)},_mouseDown:function(a){a.originalEvent= -a.originalEvent||{};if(!a.originalEvent.mouseHandled){this._mouseStarted&&this._mouseUp(a);this._mouseDownEvent=a;var c=this,e=a.which==1,f=typeof this.options.cancel=="string"?b(a.target).closest(this.options.cancel).length:false;if(!e||f||!this._mouseCapture(a))return true;this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet)this._mouseDelayTimer=setTimeout(function(){c.mouseDelayMet=true},this.options.delay);if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a)){this._mouseStarted=this._mouseStart(a)!== -false;if(!this._mouseStarted){a.preventDefault();return true}}true===b.data(a.target,this.widgetName+".preventClickEvent")&&b.removeData(a.target,this.widgetName+".preventClickEvent");this._mouseMoveDelegate=function(d){return c._mouseMove(d)};this._mouseUpDelegate=function(d){return c._mouseUp(d)};b(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);a.preventDefault();return a.originalEvent.mouseHandled=true}},_mouseMove:function(a){if(b.browser.msie&& -!(document.documentMode>=9)&&!a.button)return this._mouseUp(a);if(this._mouseStarted){this._mouseDrag(a);return a.preventDefault()}if(this._mouseDistanceMet(a)&&this._mouseDelayMet(a))(this._mouseStarted=this._mouseStart(this._mouseDownEvent,a)!==false)?this._mouseDrag(a):this._mouseUp(a);return!this._mouseStarted},_mouseUp:function(a){b(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted= -false;a.target==this._mouseDownEvent.target&&b.data(a.target,this.widgetName+".preventClickEvent",true);this._mouseStop(a)}return false},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return true}})})(jQuery); -;/* - * jQuery UI Position 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Position - */ -(function(c){c.ui=c.ui||{};var n=/left|center|right/,o=/top|center|bottom/,t=c.fn.position,u=c.fn.offset;c.fn.position=function(b){if(!b||!b.of)return t.apply(this,arguments);b=c.extend({},b);var a=c(b.of),d=a[0],g=(b.collision||"flip").split(" "),e=b.offset?b.offset.split(" "):[0,0],h,k,j;if(d.nodeType===9){h=a.width();k=a.height();j={top:0,left:0}}else if(d.setTimeout){h=a.width();k=a.height();j={top:a.scrollTop(),left:a.scrollLeft()}}else if(d.preventDefault){b.at="left top";h=k=0;j={top:b.of.pageY, -left:b.of.pageX}}else{h=a.outerWidth();k=a.outerHeight();j=a.offset()}c.each(["my","at"],function(){var f=(b[this]||"").split(" ");if(f.length===1)f=n.test(f[0])?f.concat(["center"]):o.test(f[0])?["center"].concat(f):["center","center"];f[0]=n.test(f[0])?f[0]:"center";f[1]=o.test(f[1])?f[1]:"center";b[this]=f});if(g.length===1)g[1]=g[0];e[0]=parseInt(e[0],10)||0;if(e.length===1)e[1]=e[0];e[1]=parseInt(e[1],10)||0;if(b.at[0]==="right")j.left+=h;else if(b.at[0]==="center")j.left+=h/2;if(b.at[1]==="bottom")j.top+= -k;else if(b.at[1]==="center")j.top+=k/2;j.left+=e[0];j.top+=e[1];return this.each(function(){var f=c(this),l=f.outerWidth(),m=f.outerHeight(),p=parseInt(c.curCSS(this,"marginLeft",true))||0,q=parseInt(c.curCSS(this,"marginTop",true))||0,v=l+p+(parseInt(c.curCSS(this,"marginRight",true))||0),w=m+q+(parseInt(c.curCSS(this,"marginBottom",true))||0),i=c.extend({},j),r;if(b.my[0]==="right")i.left-=l;else if(b.my[0]==="center")i.left-=l/2;if(b.my[1]==="bottom")i.top-=m;else if(b.my[1]==="center")i.top-= -m/2;i.left=Math.round(i.left);i.top=Math.round(i.top);r={left:i.left-p,top:i.top-q};c.each(["left","top"],function(s,x){c.ui.position[g[s]]&&c.ui.position[g[s]][x](i,{targetWidth:h,targetHeight:k,elemWidth:l,elemHeight:m,collisionPosition:r,collisionWidth:v,collisionHeight:w,offset:e,my:b.my,at:b.at})});c.fn.bgiframe&&f.bgiframe();f.offset(c.extend(i,{using:b.using}))})};c.ui.position={fit:{left:function(b,a){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();b.left= -d>0?b.left-d:Math.max(b.left-a.collisionPosition.left,b.left)},top:function(b,a){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();b.top=d>0?b.top-d:Math.max(b.top-a.collisionPosition.top,b.top)}},flip:{left:function(b,a){if(a.at[0]!=="center"){var d=c(window);d=a.collisionPosition.left+a.collisionWidth-d.width()-d.scrollLeft();var g=a.my[0]==="left"?-a.elemWidth:a.my[0]==="right"?a.elemWidth:0,e=a.at[0]==="left"?a.targetWidth:-a.targetWidth,h=-2*a.offset[0];b.left+= -a.collisionPosition.left<0?g+e+h:d>0?g+e+h:0}},top:function(b,a){if(a.at[1]!=="center"){var d=c(window);d=a.collisionPosition.top+a.collisionHeight-d.height()-d.scrollTop();var g=a.my[1]==="top"?-a.elemHeight:a.my[1]==="bottom"?a.elemHeight:0,e=a.at[1]==="top"?a.targetHeight:-a.targetHeight,h=-2*a.offset[1];b.top+=a.collisionPosition.top<0?g+e+h:d>0?g+e+h:0}}}};if(!c.offset.setOffset){c.offset.setOffset=function(b,a){if(/static/.test(c.curCSS(b,"position")))b.style.position="relative";var d=c(b), -g=d.offset(),e=parseInt(c.curCSS(b,"top",true),10)||0,h=parseInt(c.curCSS(b,"left",true),10)||0;g={top:a.top-g.top+e,left:a.left-g.left+h};"using"in a?a.using.call(b,g):d.css(g)};c.fn.offset=function(b){var a=this[0];if(!a||!a.ownerDocument)return null;if(b)return this.each(function(){c.offset.setOffset(this,b)});return u.call(this)}}})(jQuery); -;/* - * jQuery UI Draggable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Draggables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(d){d.widget("ui.draggable",d.ui.mouse,{widgetEventPrefix:"drag",options:{addClasses:true,appendTo:"parent",axis:false,connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false},_create:function(){if(this.options.helper== -"original"&&!/^(?:r|a|f)/.test(this.element.css("position")))this.element[0].style.position="relative";this.options.addClasses&&this.element.addClass("ui-draggable");this.options.disabled&&this.element.addClass("ui-draggable-disabled");this._mouseInit()},destroy:function(){if(this.element.data("draggable")){this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy();return this}},_mouseCapture:function(a){var b= -this.options;if(this.helper||b.disabled||d(a.target).is(".ui-resizable-handle"))return false;this.handle=this._getHandle(a);if(!this.handle)return false;d(b.iframeFix===true?"iframe":b.iframeFix).each(function(){d('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1E3}).css(d(this).offset()).appendTo("body")});return true},_mouseStart:function(a){var b=this.options;this.helper= -this._createHelper(a);this._cacheHelperProportions();if(d.ui.ddmanager)d.ui.ddmanager.current=this;this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.positionAbs=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}); -this.originalPosition=this.position=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);b.containment&&this._setContainment();if(this._trigger("start",a)===false){this._clear();return false}this._cacheHelperProportions();d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.helper.addClass("ui-draggable-dragging");this._mouseDrag(a,true);d.ui.ddmanager&&d.ui.ddmanager.dragStart(this,a);return true}, -_mouseDrag:function(a,b){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!b){b=this._uiHash();if(this._trigger("drag",a,b)===false){this._mouseUp({});return false}this.position=b.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);return false},_mouseStop:function(a){var b= -false;if(d.ui.ddmanager&&!this.options.dropBehaviour)b=d.ui.ddmanager.drop(this,a);if(this.dropped){b=this.dropped;this.dropped=false}if((!this.element[0]||!this.element[0].parentNode)&&this.options.helper=="original")return false;if(this.options.revert=="invalid"&&!b||this.options.revert=="valid"&&b||this.options.revert===true||d.isFunction(this.options.revert)&&this.options.revert.call(this.element,b)){var c=this;d(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration, -10),function(){c._trigger("stop",a)!==false&&c._clear()})}else this._trigger("stop",a)!==false&&this._clear();return false},_mouseUp:function(a){this.options.iframeFix===true&&d("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)});d.ui.ddmanager&&d.ui.ddmanager.dragStop(this,a);return d.ui.mouse.prototype._mouseUp.call(this,a)},cancel:function(){this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear();return this},_getHandle:function(a){var b=!this.options.handle|| -!d(this.options.handle,this.element).length?true:false;d(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==a.target)b=true});return b},_createHelper:function(a){var b=this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a])):b.helper=="clone"?this.element.clone().removeAttr("id"):this.element;a.parents("body").length||a.appendTo(b.appendTo=="parent"?this.element[0].parentNode:b.appendTo);a[0]!=this.element[0]&&!/(fixed|absolute)/.test(a.css("position"))&& -a.css("position","absolute");return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top=this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent= -this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a={top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"), -10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.element.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"), -10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[a.containment=="document"?0:d(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,a.containment=="document"?0:d(window).scrollTop()-this.offset.relative.top-this.offset.parent.top, -(a.containment=="document"?0:d(window).scrollLeft())+d(a.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a.containment=="document"?0:d(window).scrollTop())+(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)&&a.containment.constructor!=Array){a=d(a.containment);var b=a[0];if(b){a.offset();var c=d(b).css("overflow")!= -"hidden";this.containment=[(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0),(parseInt(d(b).css("borderTopWidth"),10)||0)+(parseInt(d(b).css("paddingTop"),10)||0),(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"), -10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom];this.relative_container=a}}else if(a.containment.constructor==Array)this.containment=a.containment},_convertPositionTo:function(a,b){if(!b)b=this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName);return{top:b.top+ -this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&& -!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,f=/(html|body)/i.test(c[0].tagName),e=a.pageX,h=a.pageY;if(this.originalPosition){var g;if(this.containment){if(this.relative_container){g=this.relative_container.offset();g=[this.containment[0]+g.left,this.containment[1]+g.top,this.containment[2]+g.left,this.containment[3]+g.top]}else g=this.containment;if(a.pageX-this.offset.click.left<g[0])e=g[0]+this.offset.click.left; -if(a.pageY-this.offset.click.top<g[1])h=g[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>g[2])e=g[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>g[3])h=g[3]+this.offset.click.top}if(b.grid){h=b.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/b.grid[1])*b.grid[1]:this.originalPageY;h=g?!(h-this.offset.click.top<g[1]||h-this.offset.click.top>g[3])?h:!(h-this.offset.click.top<g[1])?h-b.grid[1]:h+b.grid[1]:h;e=b.grid[0]?this.originalPageX+Math.round((e-this.originalPageX)/ -b.grid[0])*b.grid[0]:this.originalPageX;e=g?!(e-this.offset.click.left<g[0]||e-this.offset.click.left>g[2])?e:!(e-this.offset.click.left<g[0])?e-b.grid[0]:e+b.grid[0]:e}}return{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&d.browser.version<526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():f?0:c.scrollTop()),left:e-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&d.browser.version< -526&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():f?0:c.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove();this.helper=null;this.cancelHelperRemoval=false},_trigger:function(a,b,c){c=c||this._uiHash();d.ui.plugin.call(this,a,[b,c]);if(a=="drag")this.positionAbs=this._convertPositionTo("absolute");return d.Widget.prototype._trigger.call(this,a,b, -c)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}});d.extend(d.ui.draggable,{version:"1.8.15"});d.ui.plugin.add("draggable","connectToSortable",{start:function(a,b){var c=d(this).data("draggable"),f=c.options,e=d.extend({},b,{item:c.element});c.sortables=[];d(f.connectToSortable).each(function(){var h=d.data(this,"sortable");if(h&&!h.options.disabled){c.sortables.push({instance:h,shouldRevert:h.options.revert}); -h.refreshPositions();h._trigger("activate",a,e)}})},stop:function(a,b){var c=d(this).data("draggable"),f=d.extend({},b,{item:c.element});d.each(c.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;c.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert)this.instance.options.revert=true;this.instance._mouseStop(a);this.instance.options.helper=this.instance.options._helper;c.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})}else{this.instance.cancelHelperRemoval= -false;this.instance._trigger("deactivate",a,f)}})},drag:function(a,b){var c=d(this).data("draggable"),f=this;d.each(c.sortables,function(){this.instance.positionAbs=c.positionAbs;this.instance.helperProportions=c.helperProportions;this.instance.offset.click=c.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=d(f).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",true); -this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return b.helper[0]};a.target=this.instance.currentItem[0];this.instance._mouseCapture(a,true);this.instance._mouseStart(a,true,true);this.instance.offset.click.top=c.offset.click.top;this.instance.offset.click.left=c.offset.click.left;this.instance.offset.parent.left-=c.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=c.offset.parent.top-this.instance.offset.parent.top; -c._trigger("toSortable",a);c.dropped=this.instance.element;c.currentItem=c.element;this.instance.fromOutside=c}this.instance.currentItem&&this.instance._mouseDrag(a)}else if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",a,this.instance._uiHash(this.instance));this.instance._mouseStop(a,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();this.instance.placeholder&& -this.instance.placeholder.remove();c._trigger("fromSortable",a);c.dropped=false}})}});d.ui.plugin.add("draggable","cursor",{start:function(){var a=d("body"),b=d(this).data("draggable").options;if(a.css("cursor"))b._cursor=a.css("cursor");a.css("cursor",b.cursor)},stop:function(){var a=d(this).data("draggable").options;a._cursor&&d("body").css("cursor",a._cursor)}});d.ui.plugin.add("draggable","opacity",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("opacity"))b._opacity= -a.css("opacity");a.css("opacity",b.opacity)},stop:function(a,b){a=d(this).data("draggable").options;a._opacity&&d(b.helper).css("opacity",a._opacity)}});d.ui.plugin.add("draggable","scroll",{start:function(){var a=d(this).data("draggable");if(a.scrollParent[0]!=document&&a.scrollParent[0].tagName!="HTML")a.overflowOffset=a.scrollParent.offset()},drag:function(a){var b=d(this).data("draggable"),c=b.options,f=false;if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){if(!c.axis||c.axis!= -"x")if(b.overflowOffset.top+b.scrollParent[0].offsetHeight-a.pageY<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop+c.scrollSpeed;else if(a.pageY-b.overflowOffset.top<c.scrollSensitivity)b.scrollParent[0].scrollTop=f=b.scrollParent[0].scrollTop-c.scrollSpeed;if(!c.axis||c.axis!="y")if(b.overflowOffset.left+b.scrollParent[0].offsetWidth-a.pageX<c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft+c.scrollSpeed;else if(a.pageX-b.overflowOffset.left< -c.scrollSensitivity)b.scrollParent[0].scrollLeft=f=b.scrollParent[0].scrollLeft-c.scrollSpeed}else{if(!c.axis||c.axis!="x")if(a.pageY-d(document).scrollTop()<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()-c.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<c.scrollSensitivity)f=d(document).scrollTop(d(document).scrollTop()+c.scrollSpeed);if(!c.axis||c.axis!="y")if(a.pageX-d(document).scrollLeft()<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()- -c.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<c.scrollSensitivity)f=d(document).scrollLeft(d(document).scrollLeft()+c.scrollSpeed)}f!==false&&d.ui.ddmanager&&!c.dropBehaviour&&d.ui.ddmanager.prepareOffsets(b,a)}});d.ui.plugin.add("draggable","snap",{start:function(){var a=d(this).data("draggable"),b=a.options;a.snapElements=[];d(b.snap.constructor!=String?b.snap.items||":data(draggable)":b.snap).each(function(){var c=d(this),f=c.offset();this!=a.element[0]&&a.snapElements.push({item:this, -width:c.outerWidth(),height:c.outerHeight(),top:f.top,left:f.left})})},drag:function(a,b){for(var c=d(this).data("draggable"),f=c.options,e=f.snapTolerance,h=b.offset.left,g=h+c.helperProportions.width,n=b.offset.top,o=n+c.helperProportions.height,i=c.snapElements.length-1;i>=0;i--){var j=c.snapElements[i].left,l=j+c.snapElements[i].width,k=c.snapElements[i].top,m=k+c.snapElements[i].height;if(j-e<h&&h<l+e&&k-e<n&&n<m+e||j-e<h&&h<l+e&&k-e<o&&o<m+e||j-e<g&&g<l+e&&k-e<n&&n<m+e||j-e<g&&g<l+e&&k-e<o&& -o<m+e){if(f.snapMode!="inner"){var p=Math.abs(k-o)<=e,q=Math.abs(m-n)<=e,r=Math.abs(j-g)<=e,s=Math.abs(l-h)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k-c.helperProportions.height,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j-c.helperProportions.width}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l}).left-c.margins.left}var t= -p||q||r||s;if(f.snapMode!="outer"){p=Math.abs(k-n)<=e;q=Math.abs(m-o)<=e;r=Math.abs(j-h)<=e;s=Math.abs(l-g)<=e;if(p)b.position.top=c._convertPositionTo("relative",{top:k,left:0}).top-c.margins.top;if(q)b.position.top=c._convertPositionTo("relative",{top:m-c.helperProportions.height,left:0}).top-c.margins.top;if(r)b.position.left=c._convertPositionTo("relative",{top:0,left:j}).left-c.margins.left;if(s)b.position.left=c._convertPositionTo("relative",{top:0,left:l-c.helperProportions.width}).left-c.margins.left}if(!c.snapElements[i].snapping&& -(p||q||r||s||t))c.options.snap.snap&&c.options.snap.snap.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=p||q||r||s||t}else{c.snapElements[i].snapping&&c.options.snap.release&&c.options.snap.release.call(c.element,a,d.extend(c._uiHash(),{snapItem:c.snapElements[i].item}));c.snapElements[i].snapping=false}}}});d.ui.plugin.add("draggable","stack",{start:function(){var a=d(this).data("draggable").options;a=d.makeArray(d(a.stack)).sort(function(c,f){return(parseInt(d(c).css("zIndex"), -10)||0)-(parseInt(d(f).css("zIndex"),10)||0)});if(a.length){var b=parseInt(a[0].style.zIndex)||0;d(a).each(function(c){this.style.zIndex=b+c});this[0].style.zIndex=b+a.length}}});d.ui.plugin.add("draggable","zIndex",{start:function(a,b){a=d(b.helper);b=d(this).data("draggable").options;if(a.css("zIndex"))b._zIndex=a.css("zIndex");a.css("zIndex",b.zIndex)},stop:function(a,b){a=d(this).data("draggable").options;a._zIndex&&d(b.helper).css("zIndex",a._zIndex)}})})(jQuery); -;/* - * jQuery UI Droppable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Droppables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.mouse.js - * jquery.ui.draggable.js - */ -(function(d){d.widget("ui.droppable",{widgetEventPrefix:"drop",options:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"},_create:function(){var a=this.options,b=a.accept;this.isover=0;this.isout=1;this.accept=d.isFunction(b)?b:function(c){return c.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};d.ui.ddmanager.droppables[a.scope]=d.ui.ddmanager.droppables[a.scope]||[];d.ui.ddmanager.droppables[a.scope].push(this); -a.addClasses&&this.element.addClass("ui-droppable")},destroy:function(){for(var a=d.ui.ddmanager.droppables[this.options.scope],b=0;b<a.length;b++)a[b]==this&&a.splice(b,1);this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable");return this},_setOption:function(a,b){if(a=="accept")this.accept=d.isFunction(b)?b:function(c){return c.is(b)};d.Widget.prototype._setOption.apply(this,arguments)},_activate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&& -this.element.addClass(this.options.activeClass);b&&this._trigger("activate",a,this.ui(b))},_deactivate:function(a){var b=d.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass);b&&this._trigger("deactivate",a,this.ui(b))},_over:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.addClass(this.options.hoverClass); -this._trigger("over",a,this.ui(b))}},_out:function(a){var b=d.ui.ddmanager.current;if(!(!b||(b.currentItem||b.element)[0]==this.element[0]))if(this.accept.call(this.element[0],b.currentItem||b.element)){this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("out",a,this.ui(b))}},_drop:function(a,b){var c=b||d.ui.ddmanager.current;if(!c||(c.currentItem||c.element)[0]==this.element[0])return false;var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var g= -d.data(this,"droppable");if(g.options.greedy&&!g.options.disabled&&g.options.scope==c.options.scope&&g.accept.call(g.element[0],c.currentItem||c.element)&&d.ui.intersect(c,d.extend(g,{offset:g.element.offset()}),g.options.tolerance)){e=true;return false}});if(e)return false;if(this.accept.call(this.element[0],c.currentItem||c.element)){this.options.activeClass&&this.element.removeClass(this.options.activeClass);this.options.hoverClass&&this.element.removeClass(this.options.hoverClass);this._trigger("drop", -a,this.ui(c));return this.element}return false},ui:function(a){return{draggable:a.currentItem||a.element,helper:a.helper,position:a.position,offset:a.positionAbs}}});d.extend(d.ui.droppable,{version:"1.8.15"});d.ui.intersect=function(a,b,c){if(!b.offset)return false;var e=(a.positionAbs||a.position.absolute).left,g=e+a.helperProportions.width,f=(a.positionAbs||a.position.absolute).top,h=f+a.helperProportions.height,i=b.offset.left,k=i+b.proportions.width,j=b.offset.top,l=j+b.proportions.height; -switch(c){case "fit":return i<=e&&g<=k&&j<=f&&h<=l;case "intersect":return i<e+a.helperProportions.width/2&&g-a.helperProportions.width/2<k&&j<f+a.helperProportions.height/2&&h-a.helperProportions.height/2<l;case "pointer":return d.ui.isOver((a.positionAbs||a.position.absolute).top+(a.clickOffset||a.offset.click).top,(a.positionAbs||a.position.absolute).left+(a.clickOffset||a.offset.click).left,j,i,b.proportions.height,b.proportions.width);case "touch":return(f>=j&&f<=l||h>=j&&h<=l||f<j&&h>l)&&(e>= -i&&e<=k||g>=i&&g<=k||e<i&&g>k);default:return false}};d.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(a,b){var c=d.ui.ddmanager.droppables[a.options.scope]||[],e=b?b.type:null,g=(a.currentItem||a.element).find(":data(droppable)").andSelf(),f=0;a:for(;f<c.length;f++)if(!(c[f].options.disabled||a&&!c[f].accept.call(c[f].element[0],a.currentItem||a.element))){for(var h=0;h<g.length;h++)if(g[h]==c[f].element[0]){c[f].proportions.height=0;continue a}c[f].visible=c[f].element.css("display")!= -"none";if(c[f].visible){e=="mousedown"&&c[f]._activate.call(c[f],b);c[f].offset=c[f].element.offset();c[f].proportions={width:c[f].element[0].offsetWidth,height:c[f].element[0].offsetHeight}}}},drop:function(a,b){var c=false;d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(this.options){if(!this.options.disabled&&this.visible&&d.ui.intersect(a,this,this.options.tolerance))c=c||this._drop.call(this,b);if(!this.options.disabled&&this.visible&&this.accept.call(this.element[0],a.currentItem|| -a.element)){this.isout=1;this.isover=0;this._deactivate.call(this,b)}}});return c},dragStart:function(a,b){a.element.parentsUntil("body").bind("scroll.droppable",function(){a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)})},drag:function(a,b){a.options.refreshPositions&&d.ui.ddmanager.prepareOffsets(a,b);d.each(d.ui.ddmanager.droppables[a.options.scope]||[],function(){if(!(this.options.disabled||this.greedyChild||!this.visible)){var c=d.ui.intersect(a,this,this.options.tolerance);if(c= -!c&&this.isover==1?"isout":c&&this.isover==0?"isover":null){var e;if(this.options.greedy){var g=this.element.parents(":data(droppable):eq(0)");if(g.length){e=d.data(g[0],"droppable");e.greedyChild=c=="isover"?1:0}}if(e&&c=="isover"){e.isover=0;e.isout=1;e._out.call(e,b)}this[c]=1;this[c=="isout"?"isover":"isout"]=0;this[c=="isover"?"_over":"_out"].call(this,b);if(e&&c=="isout"){e.isout=0;e.isover=1;e._over.call(e,b)}}}})},dragStop:function(a,b){a.element.parentsUntil("body").unbind("scroll.droppable"); -a.options.refreshPositions||d.ui.ddmanager.prepareOffsets(a,b)}}})(jQuery); -;/* - * jQuery UI Resizable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Resizables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(e){e.widget("ui.resizable",e.ui.mouse,{widgetEventPrefix:"resize",options:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,containment:false,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1E3},_create:function(){var b=this,a=this.options;this.element.addClass("ui-resizable");e.extend(this,{_aspectRatio:!!a.aspectRatio,aspectRatio:a.aspectRatio,originalElement:this.element, -_proportionallyResizeElements:[],_helper:a.helper||a.ghost||a.animate?a.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){/relative/.test(this.element.css("position"))&&e.browser.opera&&this.element.css({position:"relative",top:"auto",left:"auto"});this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(), -top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle= -this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=a.handles||(!e(".ui-resizable-handle",this.element).length?"e,s,se":{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne", -nw:".ui-resizable-nw"});if(this.handles.constructor==String){if(this.handles=="all")this.handles="n,e,s,w,se,sw,ne,nw";var c=this.handles.split(",");this.handles={};for(var d=0;d<c.length;d++){var f=e.trim(c[d]),g=e('<div class="ui-resizable-handle '+("ui-resizable-"+f)+'"></div>');/sw|se|ne|nw/.test(f)&&g.css({zIndex:++a.zIndex});"se"==f&&g.addClass("ui-icon ui-icon-gripsmall-diagonal-se");this.handles[f]=".ui-resizable-"+f;this.element.append(g)}}this._renderAxis=function(h){h=h||this.element;for(var i in this.handles){if(this.handles[i].constructor== -String)this.handles[i]=e(this.handles[i],this.element).show();if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var j=e(this.handles[i],this.element),l=0;l=/sw|ne|nw|se|n|s/.test(i)?j.outerHeight():j.outerWidth();j=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join("");h.css(j,l);this._proportionallyResize()}e(this.handles[i])}};this._renderAxis(this.element);this._handles=e(".ui-resizable-handle",this.element).disableSelection(); -this._handles.mouseover(function(){if(!b.resizing){if(this.className)var h=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);b.axis=h&&h[1]?h[1]:"se"}});if(a.autoHide){this._handles.hide();e(this.element).addClass("ui-resizable-autohide").hover(function(){if(!a.disabled){e(this).removeClass("ui-resizable-autohide");b._handles.show()}},function(){if(!a.disabled)if(!b.resizing){e(this).addClass("ui-resizable-autohide");b._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy(); -var b=function(c){e(c).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){b(this.element);var a=this.element;a.after(this.originalElement.css({position:a.css("position"),width:a.outerWidth(),height:a.outerHeight(),top:a.css("top"),left:a.css("left")})).remove()}this.originalElement.css("resize",this.originalResizeStyle);b(this.originalElement);return this},_mouseCapture:function(b){var a= -false;for(var c in this.handles)if(e(this.handles[c])[0]==b.target)a=true;return!this.options.disabled&&a},_mouseStart:function(b){var a=this.options,c=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()};if(d.is(".ui-draggable")||/absolute/.test(d.css("position")))d.css({position:"absolute",top:c.top,left:c.left});e.browser.opera&&/relative/.test(d.css("position"))&&d.css({position:"relative",top:"auto",left:"auto"}); -this._renderProxy();c=m(this.helper.css("left"));var f=m(this.helper.css("top"));if(a.containment){c+=e(a.containment).scrollLeft()||0;f+=e(a.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:c,top:f};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:c,top:f};this.sizeDiff= -{width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:b.pageX,top:b.pageY};this.aspectRatio=typeof a.aspectRatio=="number"?a.aspectRatio:this.originalSize.width/this.originalSize.height||1;a=e(".ui-resizable-"+this.axis).css("cursor");e("body").css("cursor",a=="auto"?this.axis+"-resize":a);d.addClass("ui-resizable-resizing");this._propagate("start",b);return true},_mouseDrag:function(b){var a=this.helper,c=this.originalMousePosition,d=this._change[this.axis]; -if(!d)return false;c=d.apply(this,[b,b.pageX-c.left||0,b.pageY-c.top||0]);this._updateVirtualBoundaries(b.shiftKey);if(this._aspectRatio||b.shiftKey)c=this._updateRatio(c,b);c=this._respectSize(c,b);this._propagate("resize",b);a.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize();this._updateCache(c);this._trigger("resize",b,this.ui());return false}, -_mouseStop:function(b){this.resizing=false;var a=this.options,c=this;if(this._helper){var d=this._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName);d=f&&e.ui.hasScroll(d[0],"left")?0:c.sizeDiff.height;f=f?0:c.sizeDiff.width;f={width:c.helper.width()-f,height:c.helper.height()-d};d=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null;var g=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null;a.animate||this.element.css(e.extend(f, -{top:g,left:d}));c.helper.height(c.size.height);c.helper.width(c.size.width);this._helper&&!a.animate&&this._proportionallyResize()}e("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",b);this._helper&&this.helper.remove();return false},_updateVirtualBoundaries:function(b){var a=this.options,c,d,f;a={minWidth:k(a.minWidth)?a.minWidth:0,maxWidth:k(a.maxWidth)?a.maxWidth:Infinity,minHeight:k(a.minHeight)?a.minHeight:0,maxHeight:k(a.maxHeight)?a.maxHeight: -Infinity};if(this._aspectRatio||b){b=a.minHeight*this.aspectRatio;d=a.minWidth/this.aspectRatio;c=a.maxHeight*this.aspectRatio;f=a.maxWidth/this.aspectRatio;if(b>a.minWidth)a.minWidth=b;if(d>a.minHeight)a.minHeight=d;if(c<a.maxWidth)a.maxWidth=c;if(f<a.maxHeight)a.maxHeight=f}this._vBoundaries=a},_updateCache:function(b){this.offset=this.helper.offset();if(k(b.left))this.position.left=b.left;if(k(b.top))this.position.top=b.top;if(k(b.height))this.size.height=b.height;if(k(b.width))this.size.width= -b.width},_updateRatio:function(b){var a=this.position,c=this.size,d=this.axis;if(k(b.height))b.width=b.height*this.aspectRatio;else if(k(b.width))b.height=b.width/this.aspectRatio;if(d=="sw"){b.left=a.left+(c.width-b.width);b.top=null}if(d=="nw"){b.top=a.top+(c.height-b.height);b.left=a.left+(c.width-b.width)}return b},_respectSize:function(b){var a=this._vBoundaries,c=this.axis,d=k(b.width)&&a.maxWidth&&a.maxWidth<b.width,f=k(b.height)&&a.maxHeight&&a.maxHeight<b.height,g=k(b.width)&&a.minWidth&& -a.minWidth>b.width,h=k(b.height)&&a.minHeight&&a.minHeight>b.height;if(g)b.width=a.minWidth;if(h)b.height=a.minHeight;if(d)b.width=a.maxWidth;if(f)b.height=a.maxHeight;var i=this.originalPosition.left+this.originalSize.width,j=this.position.top+this.size.height,l=/sw|nw|w/.test(c);c=/nw|ne|n/.test(c);if(g&&l)b.left=i-a.minWidth;if(d&&l)b.left=i-a.maxWidth;if(h&&c)b.top=j-a.minHeight;if(f&&c)b.top=j-a.maxHeight;if((a=!b.width&&!b.height)&&!b.left&&b.top)b.top=null;else if(a&&!b.top&&b.left)b.left= -null;return b},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var b=this.helper||this.element,a=0;a<this._proportionallyResizeElements.length;a++){var c=this._proportionallyResizeElements[a];if(!this.borderDif){var d=[c.css("borderTopWidth"),c.css("borderRightWidth"),c.css("borderBottomWidth"),c.css("borderLeftWidth")],f=[c.css("paddingTop"),c.css("paddingRight"),c.css("paddingBottom"),c.css("paddingLeft")];this.borderDif=e.map(d,function(g,h){g=parseInt(g,10)|| -0;h=parseInt(f[h],10)||0;return g+h})}e.browser.msie&&(e(b).is(":hidden")||e(b).parents(":hidden").length)||c.css({height:b.height()-this.borderDif[0]-this.borderDif[2]||0,width:b.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var b=this.options;this.elementOffset=this.element.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var a=e.browser.msie&&e.browser.version<7,c=a?1:0;a=a?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+ -a,height:this.element.outerHeight()+a,position:"absolute",left:this.elementOffset.left-c+"px",top:this.elementOffset.top-c+"px",zIndex:++b.zIndex});this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(b,a){return{width:this.originalSize.width+a}},w:function(b,a){return{left:this.originalPosition.left+a,width:this.originalSize.width-a}},n:function(b,a,c){return{top:this.originalPosition.top+c,height:this.originalSize.height-c}},s:function(b,a,c){return{height:this.originalSize.height+ -c}},se:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},sw:function(b,a,c){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[b,a,c]))},ne:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[b,a,c]))},nw:function(b,a,c){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[b,a,c]))}},_propagate:function(b,a){e.ui.plugin.call(this,b,[a,this.ui()]); -b!="resize"&&this._trigger(b,a,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}});e.extend(e.ui.resizable,{version:"1.8.15"});e.ui.plugin.add("resizable","alsoResize",{start:function(){var b=e(this).data("resizable").options,a=function(c){e(c).each(function(){var d=e(this);d.data("resizable-alsoresize",{width:parseInt(d.width(), -10),height:parseInt(d.height(),10),left:parseInt(d.css("left"),10),top:parseInt(d.css("top"),10),position:d.css("position")})})};if(typeof b.alsoResize=="object"&&!b.alsoResize.parentNode)if(b.alsoResize.length){b.alsoResize=b.alsoResize[0];a(b.alsoResize)}else e.each(b.alsoResize,function(c){a(c)});else a(b.alsoResize)},resize:function(b,a){var c=e(this).data("resizable");b=c.options;var d=c.originalSize,f=c.originalPosition,g={height:c.size.height-d.height||0,width:c.size.width-d.width||0,top:c.position.top- -f.top||0,left:c.position.left-f.left||0},h=function(i,j){e(i).each(function(){var l=e(this),q=e(this).data("resizable-alsoresize"),p={},r=j&&j.length?j:l.parents(a.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(r,function(n,o){if((n=(q[o]||0)+(g[o]||0))&&n>=0)p[o]=n||null});if(e.browser.opera&&/relative/.test(l.css("position"))){c._revertToRelativePosition=true;l.css({position:"absolute",top:"auto",left:"auto"})}l.css(p)})};typeof b.alsoResize=="object"&&!b.alsoResize.nodeType? -e.each(b.alsoResize,function(i,j){h(i,j)}):h(b.alsoResize)},stop:function(){var b=e(this).data("resizable"),a=b.options,c=function(d){e(d).each(function(){var f=e(this);f.css({position:f.data("resizable-alsoresize").position})})};if(b._revertToRelativePosition){b._revertToRelativePosition=false;typeof a.alsoResize=="object"&&!a.alsoResize.nodeType?e.each(a.alsoResize,function(d){c(d)}):c(a.alsoResize)}e(this).removeData("resizable-alsoresize")}});e.ui.plugin.add("resizable","animate",{stop:function(b){var a= -e(this).data("resizable"),c=a.options,d=a._proportionallyResizeElements,f=d.length&&/textarea/i.test(d[0].nodeName),g=f&&e.ui.hasScroll(d[0],"left")?0:a.sizeDiff.height;f={width:a.size.width-(f?0:a.sizeDiff.width),height:a.size.height-g};g=parseInt(a.element.css("left"),10)+(a.position.left-a.originalPosition.left)||null;var h=parseInt(a.element.css("top"),10)+(a.position.top-a.originalPosition.top)||null;a.element.animate(e.extend(f,h&&g?{top:h,left:g}:{}),{duration:c.animateDuration,easing:c.animateEasing, -step:function(){var i={width:parseInt(a.element.css("width"),10),height:parseInt(a.element.css("height"),10),top:parseInt(a.element.css("top"),10),left:parseInt(a.element.css("left"),10)};d&&d.length&&e(d[0]).css({width:i.width,height:i.height});a._updateCache(i);a._propagate("resize",b)}})}});e.ui.plugin.add("resizable","containment",{start:function(){var b=e(this).data("resizable"),a=b.element,c=b.options.containment;if(a=c instanceof e?c.get(0):/parent/.test(c)?a.parent().get(0):c){b.containerElement= -e(a);if(/document/.test(c)||c==document){b.containerOffset={left:0,top:0};b.containerPosition={left:0,top:0};b.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}}else{var d=e(a),f=[];e(["Top","Right","Left","Bottom"]).each(function(i,j){f[i]=m(d.css("padding"+j))});b.containerOffset=d.offset();b.containerPosition=d.position();b.containerSize={height:d.innerHeight()-f[3],width:d.innerWidth()-f[1]};c=b.containerOffset; -var g=b.containerSize.height,h=b.containerSize.width;h=e.ui.hasScroll(a,"left")?a.scrollWidth:h;g=e.ui.hasScroll(a)?a.scrollHeight:g;b.parentData={element:a,left:c.left,top:c.top,width:h,height:g}}}},resize:function(b){var a=e(this).data("resizable"),c=a.options,d=a.containerOffset,f=a.position;b=a._aspectRatio||b.shiftKey;var g={top:0,left:0},h=a.containerElement;if(h[0]!=document&&/static/.test(h.css("position")))g=d;if(f.left<(a._helper?d.left:0)){a.size.width+=a._helper?a.position.left-d.left: -a.position.left-g.left;if(b)a.size.height=a.size.width/c.aspectRatio;a.position.left=c.helper?d.left:0}if(f.top<(a._helper?d.top:0)){a.size.height+=a._helper?a.position.top-d.top:a.position.top;if(b)a.size.width=a.size.height*c.aspectRatio;a.position.top=a._helper?d.top:0}a.offset.left=a.parentData.left+a.position.left;a.offset.top=a.parentData.top+a.position.top;c=Math.abs((a._helper?a.offset.left-g.left:a.offset.left-g.left)+a.sizeDiff.width);d=Math.abs((a._helper?a.offset.top-g.top:a.offset.top- -d.top)+a.sizeDiff.height);f=a.containerElement.get(0)==a.element.parent().get(0);g=/relative|absolute/.test(a.containerElement.css("position"));if(f&&g)c-=a.parentData.left;if(c+a.size.width>=a.parentData.width){a.size.width=a.parentData.width-c;if(b)a.size.height=a.size.width/a.aspectRatio}if(d+a.size.height>=a.parentData.height){a.size.height=a.parentData.height-d;if(b)a.size.width=a.size.height*a.aspectRatio}},stop:function(){var b=e(this).data("resizable"),a=b.options,c=b.containerOffset,d=b.containerPosition, -f=b.containerElement,g=e(b.helper),h=g.offset(),i=g.outerWidth()-b.sizeDiff.width;g=g.outerHeight()-b.sizeDiff.height;b._helper&&!a.animate&&/relative/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g});b._helper&&!a.animate&&/static/.test(f.css("position"))&&e(this).css({left:h.left-d.left-c.left,width:i,height:g})}});e.ui.plugin.add("resizable","ghost",{start:function(){var b=e(this).data("resizable"),a=b.options,c=b.size;b.ghost=b.originalElement.clone();b.ghost.css({opacity:0.25, -display:"block",position:"relative",height:c.height,width:c.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof a.ghost=="string"?a.ghost:"");b.ghost.appendTo(b.helper)},resize:function(){var b=e(this).data("resizable");b.ghost&&b.ghost.css({position:"relative",height:b.size.height,width:b.size.width})},stop:function(){var b=e(this).data("resizable");b.ghost&&b.helper&&b.helper.get(0).removeChild(b.ghost.get(0))}});e.ui.plugin.add("resizable","grid",{resize:function(){var b= -e(this).data("resizable"),a=b.options,c=b.size,d=b.originalSize,f=b.originalPosition,g=b.axis;a.grid=typeof a.grid=="number"?[a.grid,a.grid]:a.grid;var h=Math.round((c.width-d.width)/(a.grid[0]||1))*(a.grid[0]||1);a=Math.round((c.height-d.height)/(a.grid[1]||1))*(a.grid[1]||1);if(/^(se|s|e)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a}else if(/^(ne)$/.test(g)){b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}else{if(/^(sw)$/.test(g)){b.size.width=d.width+h;b.size.height= -d.height+a}else{b.size.width=d.width+h;b.size.height=d.height+a;b.position.top=f.top-a}b.position.left=f.left-h}}});var m=function(b){return parseInt(b,10)||0},k=function(b){return!isNaN(parseInt(b,10))}})(jQuery); -;/* - * jQuery UI Selectable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Selectables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(e){e.widget("ui.selectable",e.ui.mouse,{options:{appendTo:"body",autoRefresh:true,distance:0,filter:"*",tolerance:"touch"},_create:function(){var c=this;this.element.addClass("ui-selectable");this.dragged=false;var f;this.refresh=function(){f=e(c.options.filter,c.element[0]);f.each(function(){var d=e(this),b=d.offset();e.data(this,"selectable-item",{element:this,$element:d,left:b.left,top:b.top,right:b.left+d.outerWidth(),bottom:b.top+d.outerHeight(),startselected:false,selected:d.hasClass("ui-selected"), -selecting:d.hasClass("ui-selecting"),unselecting:d.hasClass("ui-unselecting")})})};this.refresh();this.selectees=f.addClass("ui-selectee");this._mouseInit();this.helper=e("<div class='ui-selectable-helper'></div>")},destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item");this.element.removeClass("ui-selectable ui-selectable-disabled").removeData("selectable").unbind(".selectable");this._mouseDestroy();return this},_mouseStart:function(c){var f=this;this.opos=[c.pageX, -c.pageY];if(!this.options.disabled){var d=this.options;this.selectees=e(d.filter,this.element[0]);this._trigger("start",c);e(d.appendTo).append(this.helper);this.helper.css({left:c.clientX,top:c.clientY,width:0,height:0});d.autoRefresh&&this.refresh();this.selectees.filter(".ui-selected").each(function(){var b=e.data(this,"selectable-item");b.startselected=true;if(!c.metaKey){b.$element.removeClass("ui-selected");b.selected=false;b.$element.addClass("ui-unselecting");b.unselecting=true;f._trigger("unselecting", -c,{unselecting:b.element})}});e(c.target).parents().andSelf().each(function(){var b=e.data(this,"selectable-item");if(b){var g=!c.metaKey||!b.$element.hasClass("ui-selected");b.$element.removeClass(g?"ui-unselecting":"ui-selected").addClass(g?"ui-selecting":"ui-unselecting");b.unselecting=!g;b.selecting=g;(b.selected=g)?f._trigger("selecting",c,{selecting:b.element}):f._trigger("unselecting",c,{unselecting:b.element});return false}})}},_mouseDrag:function(c){var f=this;this.dragged=true;if(!this.options.disabled){var d= -this.options,b=this.opos[0],g=this.opos[1],h=c.pageX,i=c.pageY;if(b>h){var j=h;h=b;b=j}if(g>i){j=i;i=g;g=j}this.helper.css({left:b,top:g,width:h-b,height:i-g});this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!(!a||a.element==f.element[0])){var k=false;if(d.tolerance=="touch")k=!(a.left>h||a.right<b||a.top>i||a.bottom<g);else if(d.tolerance=="fit")k=a.left>b&&a.right<h&&a.top>g&&a.bottom<i;if(k){if(a.selected){a.$element.removeClass("ui-selected");a.selected=false}if(a.unselecting){a.$element.removeClass("ui-unselecting"); -a.unselecting=false}if(!a.selecting){a.$element.addClass("ui-selecting");a.selecting=true;f._trigger("selecting",c,{selecting:a.element})}}else{if(a.selecting)if(c.metaKey&&a.startselected){a.$element.removeClass("ui-selecting");a.selecting=false;a.$element.addClass("ui-selected");a.selected=true}else{a.$element.removeClass("ui-selecting");a.selecting=false;if(a.startselected){a.$element.addClass("ui-unselecting");a.unselecting=true}f._trigger("unselecting",c,{unselecting:a.element})}if(a.selected)if(!c.metaKey&& -!a.startselected){a.$element.removeClass("ui-selected");a.selected=false;a.$element.addClass("ui-unselecting");a.unselecting=true;f._trigger("unselecting",c,{unselecting:a.element})}}}});return false}},_mouseStop:function(c){var f=this;this.dragged=false;e(".ui-unselecting",this.element[0]).each(function(){var d=e.data(this,"selectable-item");d.$element.removeClass("ui-unselecting");d.unselecting=false;d.startselected=false;f._trigger("unselected",c,{unselected:d.element})});e(".ui-selecting",this.element[0]).each(function(){var d= -e.data(this,"selectable-item");d.$element.removeClass("ui-selecting").addClass("ui-selected");d.selecting=false;d.selected=true;d.startselected=true;f._trigger("selected",c,{selected:d.element})});this._trigger("stop",c);this.helper.remove();return false}});e.extend(e.ui.selectable,{version:"1.8.15"})})(jQuery); -;/* - * jQuery UI Sortable 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Sortables - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(d){d.widget("ui.sortable",d.ui.mouse,{widgetEventPrefix:"sort",options:{appendTo:"parent",axis:false,connectWith:false,containment:false,cursor:"auto",cursorAt:false,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1E3},_create:function(){var a=this.options;this.containerCache={};this.element.addClass("ui-sortable"); -this.refresh();this.floating=this.items.length?a.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var a=this.items.length-1;a>=0;a--)this.items[a].item.removeData("sortable-item");return this},_setOption:function(a,b){if(a=== -"disabled"){this.options[a]=b;this.widget()[b?"addClass":"removeClass"]("ui-sortable-disabled")}else d.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(a,b){if(this.reverting)return false;if(this.options.disabled||this.options.type=="static")return false;this._refreshItems(a);var c=null,e=this;d(a.target).parents().each(function(){if(d.data(this,"sortable-item")==e){c=d(this);return false}});if(d.data(a.target,"sortable-item")==e)c=d(a.target);if(!c)return false;if(this.options.handle&& -!b){var f=false;d(this.options.handle,c).find("*").andSelf().each(function(){if(this==a.target)f=true});if(!f)return false}this.currentItem=c;this._removeCurrentsFromItems();return true},_mouseStart:function(a,b,c){b=this.options;var e=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(a);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top, -left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");d.extend(this.offset,{click:{left:a.pageX-this.offset.left,top:a.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(a);this.originalPageX=a.pageX;this.originalPageY=a.pageY;b.cursorAt&&this._adjustOffsetFromHelper(b.cursorAt);this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]}; -this.helper[0]!=this.currentItem[0]&&this.currentItem.hide();this._createPlaceholder();b.containment&&this._setContainment();if(b.cursor){if(d("body").css("cursor"))this._storedCursor=d("body").css("cursor");d("body").css("cursor",b.cursor)}if(b.opacity){if(this.helper.css("opacity"))this._storedOpacity=this.helper.css("opacity");this.helper.css("opacity",b.opacity)}if(b.zIndex){if(this.helper.css("zIndex"))this._storedZIndex=this.helper.css("zIndex");this.helper.css("zIndex",b.zIndex)}if(this.scrollParent[0]!= -document&&this.scrollParent[0].tagName!="HTML")this.overflowOffset=this.scrollParent.offset();this._trigger("start",a,this._uiHash());this._preserveHelperProportions||this._cacheHelperProportions();if(!c)for(c=this.containers.length-1;c>=0;c--)this.containers[c]._trigger("activate",a,e._uiHash(this));if(d.ui.ddmanager)d.ui.ddmanager.current=this;d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this,a);this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(a); -return true},_mouseDrag:function(a){this.position=this._generatePosition(a);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs)this.lastPositionAbs=this.positionAbs;if(this.options.scroll){var b=this.options,c=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if(this.overflowOffset.top+this.scrollParent[0].offsetHeight-a.pageY<b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop+b.scrollSpeed;else if(a.pageY-this.overflowOffset.top< -b.scrollSensitivity)this.scrollParent[0].scrollTop=c=this.scrollParent[0].scrollTop-b.scrollSpeed;if(this.overflowOffset.left+this.scrollParent[0].offsetWidth-a.pageX<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft+b.scrollSpeed;else if(a.pageX-this.overflowOffset.left<b.scrollSensitivity)this.scrollParent[0].scrollLeft=c=this.scrollParent[0].scrollLeft-b.scrollSpeed}else{if(a.pageY-d(document).scrollTop()<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()- -b.scrollSpeed);else if(d(window).height()-(a.pageY-d(document).scrollTop())<b.scrollSensitivity)c=d(document).scrollTop(d(document).scrollTop()+b.scrollSpeed);if(a.pageX-d(document).scrollLeft()<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()-b.scrollSpeed);else if(d(window).width()-(a.pageX-d(document).scrollLeft())<b.scrollSensitivity)c=d(document).scrollLeft(d(document).scrollLeft()+b.scrollSpeed)}c!==false&&d.ui.ddmanager&&!b.dropBehaviour&&d.ui.ddmanager.prepareOffsets(this, -a)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(b=this.items.length-1;b>=0;b--){c=this.items[b];var e=c.item[0],f=this._intersectsWithPointer(c);if(f)if(e!=this.currentItem[0]&&this.placeholder[f==1?"next":"prev"]()[0]!=e&&!d.ui.contains(this.placeholder[0],e)&&(this.options.type=="semi-dynamic"?!d.ui.contains(this.element[0], -e):true)){this.direction=f==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(c))this._rearrange(a,c);else break;this._trigger("change",a,this._uiHash());break}}this._contactContainers(a);d.ui.ddmanager&&d.ui.ddmanager.drag(this,a);this._trigger("sort",a,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(a,b){if(a){d.ui.ddmanager&&!this.options.dropBehaviour&&d.ui.ddmanager.drop(this,a);if(this.options.revert){var c=this;b=c.placeholder.offset(); -c.reverting=true;d(this.helper).animate({left:b.left-this.offset.parent.left-c.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:b.top-this.offset.parent.top-c.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){c._clear(a)})}else this._clear(a,b);return false}},cancel:function(){var a=this;if(this.dragging){this._mouseUp({target:null});this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"): -this.currentItem.show();for(var b=this.containers.length-1;b>=0;b--){this.containers[b]._trigger("deactivate",null,a._uiHash(this));if(this.containers[b].containerCache.over){this.containers[b]._trigger("out",null,a._uiHash(this));this.containers[b].containerCache.over=0}}}if(this.placeholder){this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove();d.extend(this,{helper:null, -dragging:false,reverting:false,_noFinalSort:null});this.domPosition.prev?d(this.domPosition.prev).after(this.currentItem):d(this.domPosition.parent).prepend(this.currentItem)}return this},serialize:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};d(b).each(function(){var e=(d(a.item||this).attr(a.attribute||"id")||"").match(a.expression||/(.+)[-=_](.+)/);if(e)c.push((a.key||e[1]+"[]")+"="+(a.key&&a.expression?e[1]:e[2]))});!c.length&&a.key&&c.push(a.key+"=");return c.join("&")}, -toArray:function(a){var b=this._getItemsAsjQuery(a&&a.connected),c=[];a=a||{};b.each(function(){c.push(d(a.item||this).attr(a.attribute||"id")||"")});return c},_intersectsWith:function(a){var b=this.positionAbs.left,c=b+this.helperProportions.width,e=this.positionAbs.top,f=e+this.helperProportions.height,g=a.left,h=g+a.width,i=a.top,k=i+a.height,j=this.offset.click.top,l=this.offset.click.left;j=e+j>i&&e+j<k&&b+l>g&&b+l<h;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers|| -this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>a[this.floating?"width":"height"]?j:g<b+this.helperProportions.width/2&&c-this.helperProportions.width/2<h&&i<e+this.helperProportions.height/2&&f-this.helperProportions.height/2<k},_intersectsWithPointer:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left,a.width);b=b&&a;a=this._getDragVerticalDirection(); -var c=this._getDragHorizontalDirection();if(!b)return false;return this.floating?c&&c=="right"||a=="down"?2:1:a&&(a=="down"?2:1)},_intersectsWithSides:function(a){var b=d.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,a.top+a.height/2,a.height);a=d.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,a.left+a.width/2,a.width);var c=this._getDragVerticalDirection(),e=this._getDragHorizontalDirection();return this.floating&&e?e=="right"&&a||e=="left"&&!a:c&&(c=="down"&&b||c=="up"&&!b)}, -_getDragVerticalDirection:function(){var a=this.positionAbs.top-this.lastPositionAbs.top;return a!=0&&(a>0?"down":"up")},_getDragHorizontalDirection:function(){var a=this.positionAbs.left-this.lastPositionAbs.left;return a!=0&&(a>0?"right":"left")},refresh:function(a){this._refreshItems(a);this.refreshPositions();return this},_connectWith:function(){var a=this.options;return a.connectWith.constructor==String?[a.connectWith]:a.connectWith},_getItemsAsjQuery:function(a){var b=[],c=[],e=this._connectWith(); -if(e&&a)for(a=e.length-1;a>=0;a--)for(var f=d(e[a]),g=f.length-1;g>=0;g--){var h=d.data(f[g],"sortable");if(h&&h!=this&&!h.options.disabled)c.push([d.isFunction(h.options.items)?h.options.items.call(h.element):d(h.options.items,h.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),h])}c.push([d.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):d(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), -this]);for(a=c.length-1;a>=0;a--)c[a][0].each(function(){b.push(this)});return d(b)},_removeCurrentsFromItems:function(){for(var a=this.currentItem.find(":data(sortable-item)"),b=0;b<this.items.length;b++)for(var c=0;c<a.length;c++)a[c]==this.items[b].item[0]&&this.items.splice(b,1)},_refreshItems:function(a){this.items=[];this.containers=[this];var b=this.items,c=[[d.isFunction(this.options.items)?this.options.items.call(this.element[0],a,{item:this.currentItem}):d(this.options.items,this.element), -this]],e=this._connectWith();if(e)for(var f=e.length-1;f>=0;f--)for(var g=d(e[f]),h=g.length-1;h>=0;h--){var i=d.data(g[h],"sortable");if(i&&i!=this&&!i.options.disabled){c.push([d.isFunction(i.options.items)?i.options.items.call(i.element[0],a,{item:this.currentItem}):d(i.options.items,i.element),i]);this.containers.push(i)}}for(f=c.length-1;f>=0;f--){a=c[f][1];e=c[f][0];h=0;for(g=e.length;h<g;h++){i=d(e[h]);i.data("sortable-item",a);b.push({item:i,instance:a,width:0,height:0,left:0,top:0})}}},refreshPositions:function(a){if(this.offsetParent&& -this.helper)this.offset.parent=this._getParentOffset();for(var b=this.items.length-1;b>=0;b--){var c=this.items[b];if(!(c.instance!=this.currentContainer&&this.currentContainer&&c.item[0]!=this.currentItem[0])){var e=this.options.toleranceElement?d(this.options.toleranceElement,c.item):c.item;if(!a){c.width=e.outerWidth();c.height=e.outerHeight()}e=e.offset();c.left=e.left;c.top=e.top}}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(b= -this.containers.length-1;b>=0;b--){e=this.containers[b].element.offset();this.containers[b].containerCache.left=e.left;this.containers[b].containerCache.top=e.top;this.containers[b].containerCache.width=this.containers[b].element.outerWidth();this.containers[b].containerCache.height=this.containers[b].element.outerHeight()}return this},_createPlaceholder:function(a){var b=a||this,c=b.options;if(!c.placeholder||c.placeholder.constructor==String){var e=c.placeholder;c.placeholder={element:function(){var f= -d(document.createElement(b.currentItem[0].nodeName)).addClass(e||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!e)f.style.visibility="hidden";return f},update:function(f,g){if(!(e&&!c.forcePlaceholderSize)){g.height()||g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10));g.width()||g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")|| -0,10))}}}}b.placeholder=d(c.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);c.placeholder.update(b,b.placeholder)},_contactContainers:function(a){for(var b=null,c=null,e=this.containers.length-1;e>=0;e--)if(!d.ui.contains(this.currentItem[0],this.containers[e].element[0]))if(this._intersectsWith(this.containers[e].containerCache)){if(!(b&&d.ui.contains(this.containers[e].element[0],b.element[0]))){b=this.containers[e];c=e}}else if(this.containers[e].containerCache.over){this.containers[e]._trigger("out", -a,this._uiHash(this));this.containers[e].containerCache.over=0}if(b)if(this.containers.length===1){this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}else if(this.currentContainer!=this.containers[c]){b=1E4;e=null;for(var f=this.positionAbs[this.containers[c].floating?"left":"top"],g=this.items.length-1;g>=0;g--)if(d.ui.contains(this.containers[c].element[0],this.items[g].item[0])){var h=this.items[g][this.containers[c].floating?"left":"top"];if(Math.abs(h- -f)<b){b=Math.abs(h-f);e=this.items[g]}}if(e||this.options.dropOnEmpty){this.currentContainer=this.containers[c];e?this._rearrange(a,e,null,true):this._rearrange(a,null,this.containers[c].element,true);this._trigger("change",a,this._uiHash());this.containers[c]._trigger("change",a,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder);this.containers[c]._trigger("over",a,this._uiHash(this));this.containers[c].containerCache.over=1}}},_createHelper:function(a){var b= -this.options;a=d.isFunction(b.helper)?d(b.helper.apply(this.element[0],[a,this.currentItem])):b.helper=="clone"?this.currentItem.clone():this.currentItem;a.parents("body").length||d(b.appendTo!="parent"?b.appendTo:this.currentItem[0].parentNode)[0].appendChild(a[0]);if(a[0]==this.currentItem[0])this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")};if(a[0].style.width== -""||b.forceHelperSize)a.width(this.currentItem.width());if(a[0].style.height==""||b.forceHelperSize)a.height(this.currentItem.height());return a},_adjustOffsetFromHelper:function(a){if(typeof a=="string")a=a.split(" ");if(d.isArray(a))a={left:+a[0],top:+a[1]||0};if("left"in a)this.offset.click.left=a.left+this.margins.left;if("right"in a)this.offset.click.left=this.helperProportions.width-a.right+this.margins.left;if("top"in a)this.offset.click.top=a.top+this.margins.top;if("bottom"in a)this.offset.click.top= -this.helperProportions.height-a.bottom+this.margins.top},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var a=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0])){a.left+=this.scrollParent.scrollLeft();a.top+=this.scrollParent.scrollTop()}if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&d.browser.msie)a= -{top:0,left:0};return{top:a.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:a.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var a=this.currentItem.position();return{top:a.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:a.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"), -10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var a=this.options;if(a.containment=="parent")a.containment=this.helper[0].parentNode;if(a.containment=="document"||a.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,d(a.containment=="document"? -document:window).width()-this.helperProportions.width-this.margins.left,(d(a.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(a.containment)){var b=d(a.containment)[0];a=d(a.containment).offset();var c=d(b).css("overflow")!="hidden";this.containment=[a.left+(parseInt(d(b).css("borderLeftWidth"),10)||0)+(parseInt(d(b).css("paddingLeft"),10)||0)-this.margins.left,a.top+(parseInt(d(b).css("borderTopWidth"), -10)||0)+(parseInt(d(b).css("paddingTop"),10)||0)-this.margins.top,a.left+(c?Math.max(b.scrollWidth,b.offsetWidth):b.offsetWidth)-(parseInt(d(b).css("borderLeftWidth"),10)||0)-(parseInt(d(b).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,a.top+(c?Math.max(b.scrollHeight,b.offsetHeight):b.offsetHeight)-(parseInt(d(b).css("borderTopWidth"),10)||0)-(parseInt(d(b).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(a,b){if(!b)b= -this.position;a=a=="absolute"?1:-1;var c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);return{top:b.top+this.offset.relative.top*a+this.offset.parent.top*a-(d.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop())*a),left:b.left+this.offset.relative.left*a+this.offset.parent.left*a-(d.browser.safari&& -this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())*a)}},_generatePosition:function(a){var b=this.options,c=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&d.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,e=/(html|body)/i.test(c[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0]))this.offset.relative=this._getRelativeOffset(); -var f=a.pageX,g=a.pageY;if(this.originalPosition){if(this.containment){if(a.pageX-this.offset.click.left<this.containment[0])f=this.containment[0]+this.offset.click.left;if(a.pageY-this.offset.click.top<this.containment[1])g=this.containment[1]+this.offset.click.top;if(a.pageX-this.offset.click.left>this.containment[2])f=this.containment[2]+this.offset.click.left;if(a.pageY-this.offset.click.top>this.containment[3])g=this.containment[3]+this.offset.click.top}if(b.grid){g=this.originalPageY+Math.round((g- -this.originalPageY)/b.grid[1])*b.grid[1];g=this.containment?!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:!(g-this.offset.click.top<this.containment[1])?g-b.grid[1]:g+b.grid[1]:g;f=this.originalPageX+Math.round((f-this.originalPageX)/b.grid[0])*b.grid[0];f=this.containment?!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:!(f-this.offset.click.left<this.containment[0])?f-b.grid[0]:f+b.grid[0]:f}}return{top:g- -this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollTop():e?0:c.scrollTop()),left:f-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(d.browser.safari&&this.cssPosition=="fixed"?0:this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():e?0:c.scrollLeft())}},_rearrange:function(a,b,c,e){c?c[0].appendChild(this.placeholder[0]):b.item[0].parentNode.insertBefore(this.placeholder[0], -this.direction=="down"?b.item[0]:b.item[0].nextSibling);this.counter=this.counter?++this.counter:1;var f=this,g=this.counter;window.setTimeout(function(){g==f.counter&&f.refreshPositions(!e)},0)},_clear:function(a,b){this.reverting=false;var c=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem);this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var e in this._storedCSS)if(this._storedCSS[e]=="auto"||this._storedCSS[e]=="static")this._storedCSS[e]= -"";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!b&&c.push(function(f){this._trigger("receive",f,this._uiHash(this.fromOutside))});if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!b)c.push(function(f){this._trigger("update",f,this._uiHash())});if(!d.ui.contains(this.element[0],this.currentItem[0])){b||c.push(function(f){this._trigger("remove", -f,this._uiHash())});for(e=this.containers.length-1;e>=0;e--)if(d.ui.contains(this.containers[e].element[0],this.currentItem[0])&&!b){c.push(function(f){return function(g){f._trigger("receive",g,this._uiHash(this))}}.call(this,this.containers[e]));c.push(function(f){return function(g){f._trigger("update",g,this._uiHash(this))}}.call(this,this.containers[e]))}}for(e=this.containers.length-1;e>=0;e--){b||c.push(function(f){return function(g){f._trigger("deactivate",g,this._uiHash(this))}}.call(this, -this.containers[e]));if(this.containers[e].containerCache.over){c.push(function(f){return function(g){f._trigger("out",g,this._uiHash(this))}}.call(this,this.containers[e]));this.containers[e].containerCache.over=0}}this._storedCursor&&d("body").css("cursor",this._storedCursor);this._storedOpacity&&this.helper.css("opacity",this._storedOpacity);if(this._storedZIndex)this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex);this.dragging=false;if(this.cancelHelperRemoval){if(!b){this._trigger("beforeStop", -a,this._uiHash());for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}return false}b||this._trigger("beforeStop",a,this._uiHash());this.placeholder[0].parentNode.removeChild(this.placeholder[0]);this.helper[0]!=this.currentItem[0]&&this.helper.remove();this.helper=null;if(!b){for(e=0;e<c.length;e++)c[e].call(this,a);this._trigger("stop",a,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){d.Widget.prototype._trigger.apply(this,arguments)===false&&this.cancel()}, -_uiHash:function(a){var b=a||this;return{helper:b.helper,placeholder:b.placeholder||d([]),position:b.position,originalPosition:b.originalPosition,offset:b.positionAbs,item:b.currentItem,sender:a?a.element:null}}});d.extend(d.ui.sortable,{version:"1.8.15"})})(jQuery); -;/* - * jQuery UI Accordion 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Accordion - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function(c){c.widget("ui.accordion",{options:{active:0,animated:"slide",autoHeight:true,clearStyle:false,collapsible:false,event:"click",fillSpace:false,header:"> li > :first-child,> :not(li):even",icons:{header:"ui-icon-triangle-1-e",headerSelected:"ui-icon-triangle-1-s"},navigation:false,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}},_create:function(){var a=this,b=a.options;a.running=0;a.element.addClass("ui-accordion ui-widget ui-helper-reset").children("li").addClass("ui-accordion-li-fix"); -a.headers=a.element.find(b.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all").bind("mouseenter.accordion",function(){b.disabled||c(this).addClass("ui-state-hover")}).bind("mouseleave.accordion",function(){b.disabled||c(this).removeClass("ui-state-hover")}).bind("focus.accordion",function(){b.disabled||c(this).addClass("ui-state-focus")}).bind("blur.accordion",function(){b.disabled||c(this).removeClass("ui-state-focus")});a.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom"); -if(b.navigation){var d=a.element.find("a").filter(b.navigationFilter).eq(0);if(d.length){var h=d.closest(".ui-accordion-header");a.active=h.length?h:d.closest(".ui-accordion-content").prev()}}a.active=a._findActive(a.active||b.active).addClass("ui-state-default ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");a.active.next().addClass("ui-accordion-content-active");a._createIcons();a.resize();a.element.attr("role","tablist");a.headers.attr("role","tab").bind("keydown.accordion", -function(f){return a._keydown(f)}).next().attr("role","tabpanel");a.headers.not(a.active||"").attr({"aria-expanded":"false","aria-selected":"false",tabIndex:-1}).next().hide();a.active.length?a.active.attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}):a.headers.eq(0).attr("tabIndex",0);c.browser.safari||a.headers.find("a").attr("tabIndex",-1);b.event&&a.headers.bind(b.event.split(" ").join(".accordion ")+".accordion",function(f){a._clickHandler.call(a,f,this);f.preventDefault()})},_createIcons:function(){var a= -this.options;if(a.icons){c("<span></span>").addClass("ui-icon "+a.icons.header).prependTo(this.headers);this.active.children(".ui-icon").toggleClass(a.icons.header).toggleClass(a.icons.headerSelected);this.element.addClass("ui-accordion-icons")}},_destroyIcons:function(){this.headers.children(".ui-icon").remove();this.element.removeClass("ui-accordion-icons")},destroy:function(){var a=this.options;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role");this.headers.unbind(".accordion").removeClass("ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-selected").removeAttr("tabIndex"); -this.headers.find("a").removeAttr("tabIndex");this._destroyIcons();var b=this.headers.next().css("display","").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled");if(a.autoHeight||a.fillHeight)b.css("height","");return c.Widget.prototype.destroy.call(this)},_setOption:function(a,b){c.Widget.prototype._setOption.apply(this,arguments);a=="active"&&this.activate(b);if(a=="icons"){this._destroyIcons(); -b&&this._createIcons()}if(a=="disabled")this.headers.add(this.headers.next())[b?"addClass":"removeClass"]("ui-accordion-disabled ui-state-disabled")},_keydown:function(a){if(!(this.options.disabled||a.altKey||a.ctrlKey)){var b=c.ui.keyCode,d=this.headers.length,h=this.headers.index(a.target),f=false;switch(a.keyCode){case b.RIGHT:case b.DOWN:f=this.headers[(h+1)%d];break;case b.LEFT:case b.UP:f=this.headers[(h-1+d)%d];break;case b.SPACE:case b.ENTER:this._clickHandler({target:a.target},a.target); -a.preventDefault()}if(f){c(a.target).attr("tabIndex",-1);c(f).attr("tabIndex",0);f.focus();return false}return true}},resize:function(){var a=this.options,b;if(a.fillSpace){if(c.browser.msie){var d=this.element.parent().css("overflow");this.element.parent().css("overflow","hidden")}b=this.element.parent().height();c.browser.msie&&this.element.parent().css("overflow",d);this.headers.each(function(){b-=c(this).outerHeight(true)});this.headers.next().each(function(){c(this).height(Math.max(0,b-c(this).innerHeight()+ -c(this).height()))}).css("overflow","auto")}else if(a.autoHeight){b=0;this.headers.next().each(function(){b=Math.max(b,c(this).height("").height())}).height(b)}return this},activate:function(a){this.options.active=a;a=this._findActive(a)[0];this._clickHandler({target:a},a);return this},_findActive:function(a){return a?typeof a==="number"?this.headers.filter(":eq("+a+")"):this.headers.not(this.headers.not(a)):a===false?c([]):this.headers.filter(":eq(0)")},_clickHandler:function(a,b){var d=this.options; -if(!d.disabled)if(a.target){a=c(a.currentTarget||b);b=a[0]===this.active[0];d.active=d.collapsible&&b?false:this.headers.index(a);if(!(this.running||!d.collapsible&&b)){var h=this.active;j=a.next();g=this.active.next();e={options:d,newHeader:b&&d.collapsible?c([]):a,oldHeader:this.active,newContent:b&&d.collapsible?c([]):j,oldContent:g};var f=this.headers.index(this.active[0])>this.headers.index(a[0]);this.active=b?c([]):a;this._toggle(j,g,e,b,f);h.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header); -if(!b){a.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top").children(".ui-icon").removeClass(d.icons.header).addClass(d.icons.headerSelected);a.next().addClass("ui-accordion-content-active")}}}else if(d.collapsible){this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all").children(".ui-icon").removeClass(d.icons.headerSelected).addClass(d.icons.header);this.active.next().addClass("ui-accordion-content-active");var g=this.active.next(), -e={options:d,newHeader:c([]),oldHeader:d.active,newContent:c([]),oldContent:g},j=this.active=c([]);this._toggle(j,g,e)}},_toggle:function(a,b,d,h,f){var g=this,e=g.options;g.toShow=a;g.toHide=b;g.data=d;var j=function(){if(g)return g._completed.apply(g,arguments)};g._trigger("changestart",null,g.data);g.running=b.size()===0?a.size():b.size();if(e.animated){d={};d=e.collapsible&&h?{toShow:c([]),toHide:b,complete:j,down:f,autoHeight:e.autoHeight||e.fillSpace}:{toShow:a,toHide:b,complete:j,down:f,autoHeight:e.autoHeight|| -e.fillSpace};if(!e.proxied)e.proxied=e.animated;if(!e.proxiedDuration)e.proxiedDuration=e.duration;e.animated=c.isFunction(e.proxied)?e.proxied(d):e.proxied;e.duration=c.isFunction(e.proxiedDuration)?e.proxiedDuration(d):e.proxiedDuration;h=c.ui.accordion.animations;var i=e.duration,k=e.animated;if(k&&!h[k]&&!c.easing[k])k="slide";h[k]||(h[k]=function(l){this.slide(l,{easing:k,duration:i||700})});h[k](d)}else{if(e.collapsible&&h)a.toggle();else{b.hide();a.show()}j(true)}b.prev().attr({"aria-expanded":"false", -"aria-selected":"false",tabIndex:-1}).blur();a.prev().attr({"aria-expanded":"true","aria-selected":"true",tabIndex:0}).focus()},_completed:function(a){this.running=a?0:--this.running;if(!this.running){this.options.clearStyle&&this.toShow.add(this.toHide).css({height:"",overflow:""});this.toHide.removeClass("ui-accordion-content-active");if(this.toHide.length)this.toHide.parent()[0].className=this.toHide.parent()[0].className;this._trigger("change",null,this.data)}}});c.extend(c.ui.accordion,{version:"1.8.15", -animations:{slide:function(a,b){a=c.extend({easing:"swing",duration:300},a,b);if(a.toHide.size())if(a.toShow.size()){var d=a.toShow.css("overflow"),h=0,f={},g={},e;b=a.toShow;e=b[0].style.width;b.width(parseInt(b.parent().width(),10)-parseInt(b.css("paddingLeft"),10)-parseInt(b.css("paddingRight"),10)-(parseInt(b.css("borderLeftWidth"),10)||0)-(parseInt(b.css("borderRightWidth"),10)||0));c.each(["height","paddingTop","paddingBottom"],function(j,i){g[i]="hide";j=(""+c.css(a.toShow[0],i)).match(/^([\d+-.]+)(.*)$/); -f[i]={value:j[1],unit:j[2]||"px"}});a.toShow.css({height:0,overflow:"hidden"}).show();a.toHide.filter(":hidden").each(a.complete).end().filter(":visible").animate(g,{step:function(j,i){if(i.prop=="height")h=i.end-i.start===0?0:(i.now-i.start)/(i.end-i.start);a.toShow[0].style[i.prop]=h*f[i.prop].value+f[i.prop].unit},duration:a.duration,easing:a.easing,complete:function(){a.autoHeight||a.toShow.css("height","");a.toShow.css({width:e,overflow:d});a.complete()}})}else a.toHide.animate({height:"hide", -paddingTop:"hide",paddingBottom:"hide"},a);else a.toShow.animate({height:"show",paddingTop:"show",paddingBottom:"show"},a)},bounceslide:function(a){this.slide(a,{easing:a.down?"easeOutBounce":"swing",duration:a.down?1E3:200})}}})})(jQuery); -;/* - * jQuery UI Autocomplete 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Autocomplete - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.position.js - */ -(function(d){var e=0;d.widget("ui.autocomplete",{options:{appendTo:"body",autoFocus:false,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null},pending:0,_create:function(){var a=this,b=this.element[0].ownerDocument,g;this.element.addClass("ui-autocomplete-input").attr("autocomplete","off").attr({role:"textbox","aria-autocomplete":"list","aria-haspopup":"true"}).bind("keydown.autocomplete",function(c){if(!(a.options.disabled||a.element.propAttr("readOnly"))){g= -false;var f=d.ui.keyCode;switch(c.keyCode){case f.PAGE_UP:a._move("previousPage",c);break;case f.PAGE_DOWN:a._move("nextPage",c);break;case f.UP:a._move("previous",c);c.preventDefault();break;case f.DOWN:a._move("next",c);c.preventDefault();break;case f.ENTER:case f.NUMPAD_ENTER:if(a.menu.active){g=true;c.preventDefault()}case f.TAB:if(!a.menu.active)return;a.menu.select(c);break;case f.ESCAPE:a.element.val(a.term);a.close(c);break;default:clearTimeout(a.searching);a.searching=setTimeout(function(){if(a.term!= -a.element.val()){a.selectedItem=null;a.search(null,c)}},a.options.delay);break}}}).bind("keypress.autocomplete",function(c){if(g){g=false;c.preventDefault()}}).bind("focus.autocomplete",function(){if(!a.options.disabled){a.selectedItem=null;a.previous=a.element.val()}}).bind("blur.autocomplete",function(c){if(!a.options.disabled){clearTimeout(a.searching);a.closing=setTimeout(function(){a.close(c);a._change(c)},150)}});this._initSource();this.response=function(){return a._response.apply(a,arguments)}; -this.menu=d("<ul></ul>").addClass("ui-autocomplete").appendTo(d(this.options.appendTo||"body",b)[0]).mousedown(function(c){var f=a.menu.element[0];d(c.target).closest(".ui-menu-item").length||setTimeout(function(){d(document).one("mousedown",function(h){h.target!==a.element[0]&&h.target!==f&&!d.ui.contains(f,h.target)&&a.close()})},1);setTimeout(function(){clearTimeout(a.closing)},13)}).menu({focus:function(c,f){f=f.item.data("item.autocomplete");false!==a._trigger("focus",c,{item:f})&&/^key/.test(c.originalEvent.type)&& -a.element.val(f.value)},selected:function(c,f){var h=f.item.data("item.autocomplete"),i=a.previous;if(a.element[0]!==b.activeElement){a.element.focus();a.previous=i;setTimeout(function(){a.previous=i;a.selectedItem=h},1)}false!==a._trigger("select",c,{item:h})&&a.element.val(h.value);a.term=a.element.val();a.close(c);a.selectedItem=h},blur:function(){a.menu.element.is(":visible")&&a.element.val()!==a.term&&a.element.val(a.term)}}).zIndex(this.element.zIndex()+1).css({top:0,left:0}).hide().data("menu"); -d.fn.bgiframe&&this.menu.element.bgiframe()},destroy:function(){this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete").removeAttr("role").removeAttr("aria-autocomplete").removeAttr("aria-haspopup");this.menu.element.remove();d.Widget.prototype.destroy.call(this)},_setOption:function(a,b){d.Widget.prototype._setOption.apply(this,arguments);a==="source"&&this._initSource();if(a==="appendTo")this.menu.element.appendTo(d(b||"body",this.element[0].ownerDocument)[0]);a==="disabled"&& -b&&this.xhr&&this.xhr.abort()},_initSource:function(){var a=this,b,g;if(d.isArray(this.options.source)){b=this.options.source;this.source=function(c,f){f(d.ui.autocomplete.filter(b,c.term))}}else if(typeof this.options.source==="string"){g=this.options.source;this.source=function(c,f){a.xhr&&a.xhr.abort();a.xhr=d.ajax({url:g,data:c,dataType:"json",autocompleteRequest:++e,success:function(h){this.autocompleteRequest===e&&f(h)},error:function(){this.autocompleteRequest===e&&f([])}})}}else this.source= -this.options.source},search:function(a,b){a=a!=null?a:this.element.val();this.term=this.element.val();if(a.length<this.options.minLength)return this.close(b);clearTimeout(this.closing);if(this._trigger("search",b)!==false)return this._search(a)},_search:function(a){this.pending++;this.element.addClass("ui-autocomplete-loading");this.source({term:a},this.response)},_response:function(a){if(!this.options.disabled&&a&&a.length){a=this._normalize(a);this._suggest(a);this._trigger("open")}else this.close(); -this.pending--;this.pending||this.element.removeClass("ui-autocomplete-loading")},close:function(a){clearTimeout(this.closing);if(this.menu.element.is(":visible")){this.menu.element.hide();this.menu.deactivate();this._trigger("close",a)}},_change:function(a){this.previous!==this.element.val()&&this._trigger("change",a,{item:this.selectedItem})},_normalize:function(a){if(a.length&&a[0].label&&a[0].value)return a;return d.map(a,function(b){if(typeof b==="string")return{label:b,value:b};return d.extend({label:b.label|| -b.value,value:b.value||b.label},b)})},_suggest:function(a){var b=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(b,a);this.menu.deactivate();this.menu.refresh();b.show();this._resizeMenu();b.position(d.extend({of:this.element},this.options.position));this.options.autoFocus&&this.menu.next(new d.Event("mouseover"))},_resizeMenu:function(){var a=this.menu.element;a.outerWidth(Math.max(a.width("").outerWidth(),this.element.outerWidth()))},_renderMenu:function(a,b){var g=this; -d.each(b,function(c,f){g._renderItem(a,f)})},_renderItem:function(a,b){return d("<li></li>").data("item.autocomplete",b).append(d("<a></a>").text(b.label)).appendTo(a)},_move:function(a,b){if(this.menu.element.is(":visible"))if(this.menu.first()&&/^previous/.test(a)||this.menu.last()&&/^next/.test(a)){this.element.val(this.term);this.menu.deactivate()}else this.menu[a](b);else this.search(null,b)},widget:function(){return this.menu.element}});d.extend(d.ui.autocomplete,{escapeRegex:function(a){return a.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, -"\\$&")},filter:function(a,b){var g=new RegExp(d.ui.autocomplete.escapeRegex(b),"i");return d.grep(a,function(c){return g.test(c.label||c.value||c)})}})})(jQuery); -(function(d){d.widget("ui.menu",{_create:function(){var e=this;this.element.addClass("ui-menu ui-widget ui-widget-content ui-corner-all").attr({role:"listbox","aria-activedescendant":"ui-active-menuitem"}).click(function(a){if(d(a.target).closest(".ui-menu-item a").length){a.preventDefault();e.select(a)}});this.refresh()},refresh:function(){var e=this;this.element.children("li:not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","menuitem").children("a").addClass("ui-corner-all").attr("tabindex", --1).mouseenter(function(a){e.activate(a,d(this).parent())}).mouseleave(function(){e.deactivate()})},activate:function(e,a){this.deactivate();if(this.hasScroll()){var b=a.offset().top-this.element.offset().top,g=this.element.scrollTop(),c=this.element.height();if(b<0)this.element.scrollTop(g+b);else b>=c&&this.element.scrollTop(g+b-c+a.height())}this.active=a.eq(0).children("a").addClass("ui-state-hover").attr("id","ui-active-menuitem").end();this._trigger("focus",e,{item:a})},deactivate:function(){if(this.active){this.active.children("a").removeClass("ui-state-hover").removeAttr("id"); -this._trigger("blur");this.active=null}},next:function(e){this.move("next",".ui-menu-item:first",e)},previous:function(e){this.move("prev",".ui-menu-item:last",e)},first:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},last:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},move:function(e,a,b){if(this.active){e=this.active[e+"All"](".ui-menu-item").eq(0);e.length?this.activate(b,e):this.activate(b,this.element.children(a))}else this.activate(b, -this.element.children(a))},nextPage:function(e){if(this.hasScroll())if(!this.active||this.last())this.activate(e,this.element.children(".ui-menu-item:first"));else{var a=this.active.offset().top,b=this.element.height(),g=this.element.children(".ui-menu-item").filter(function(){var c=d(this).offset().top-a-b+d(this).height();return c<10&&c>-10});g.length||(g=this.element.children(".ui-menu-item:last"));this.activate(e,g)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| -this.last()?":first":":last"))},previousPage:function(e){if(this.hasScroll())if(!this.active||this.first())this.activate(e,this.element.children(".ui-menu-item:last"));else{var a=this.active.offset().top,b=this.element.height();result=this.element.children(".ui-menu-item").filter(function(){var g=d(this).offset().top-a+b-d(this).height();return g<10&&g>-10});result.length||(result=this.element.children(".ui-menu-item:first"));this.activate(e,result)}else this.activate(e,this.element.children(".ui-menu-item").filter(!this.active|| -this.first()?":last":":first"))},hasScroll:function(){return this.element.height()<this.element[d.fn.prop?"prop":"attr"]("scrollHeight")},select:function(e){this._trigger("selected",e,{item:this.active})}})})(jQuery); -;/* - * jQuery UI Button 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Button - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function(b){var h,i,j,g,l=function(){var a=b(this).find(":ui-button");setTimeout(function(){a.button("refresh")},1)},k=function(a){var c=a.name,e=a.form,f=b([]);if(c)f=e?b(e).find("[name='"+c+"']"):b("[name='"+c+"']",a.ownerDocument).filter(function(){return!this.form});return f};b.widget("ui.button",{options:{disabled:null,text:true,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset.button").bind("reset.button",l);if(typeof this.options.disabled!== -"boolean")this.options.disabled=this.element.propAttr("disabled");this._determineButtonType();this.hasTitle=!!this.buttonElement.attr("title");var a=this,c=this.options,e=this.type==="checkbox"||this.type==="radio",f="ui-state-hover"+(!e?" ui-state-active":"");if(c.label===null)c.label=this.buttonElement.html();if(this.element.is(":disabled"))c.disabled=true;this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role","button").bind("mouseenter.button",function(){if(!c.disabled){b(this).addClass("ui-state-hover"); -this===h&&b(this).addClass("ui-state-active")}}).bind("mouseleave.button",function(){c.disabled||b(this).removeClass(f)}).bind("click.button",function(d){if(c.disabled){d.preventDefault();d.stopImmediatePropagation()}});this.element.bind("focus.button",function(){a.buttonElement.addClass("ui-state-focus")}).bind("blur.button",function(){a.buttonElement.removeClass("ui-state-focus")});if(e){this.element.bind("change.button",function(){g||a.refresh()});this.buttonElement.bind("mousedown.button",function(d){if(!c.disabled){g= -false;i=d.pageX;j=d.pageY}}).bind("mouseup.button",function(d){if(!c.disabled)if(i!==d.pageX||j!==d.pageY)g=true})}if(this.type==="checkbox")this.buttonElement.bind("click.button",function(){if(c.disabled||g)return false;b(this).toggleClass("ui-state-active");a.buttonElement.attr("aria-pressed",a.element[0].checked)});else if(this.type==="radio")this.buttonElement.bind("click.button",function(){if(c.disabled||g)return false;b(this).addClass("ui-state-active");a.buttonElement.attr("aria-pressed","true"); -var d=a.element[0];k(d).not(d).map(function(){return b(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")});else{this.buttonElement.bind("mousedown.button",function(){if(c.disabled)return false;b(this).addClass("ui-state-active");h=this;b(document).one("mouseup",function(){h=null})}).bind("mouseup.button",function(){if(c.disabled)return false;b(this).removeClass("ui-state-active")}).bind("keydown.button",function(d){if(c.disabled)return false;if(d.keyCode==b.ui.keyCode.SPACE|| -d.keyCode==b.ui.keyCode.ENTER)b(this).addClass("ui-state-active")}).bind("keyup.button",function(){b(this).removeClass("ui-state-active")});this.buttonElement.is("a")&&this.buttonElement.keyup(function(d){d.keyCode===b.ui.keyCode.SPACE&&b(this).click()})}this._setOption("disabled",c.disabled);this._resetButton()},_determineButtonType:function(){this.type=this.element.is(":checkbox")?"checkbox":this.element.is(":radio")?"radio":this.element.is("input")?"input":"button";if(this.type==="checkbox"||this.type=== -"radio"){var a=this.element.parents().filter(":last"),c="label[for="+this.element.attr("id")+"]";this.buttonElement=a.find(c);if(!this.buttonElement.length){a=a.length?a.siblings():this.element.siblings();this.buttonElement=a.filter(c);if(!this.buttonElement.length)this.buttonElement=a.find(c)}this.element.addClass("ui-helper-hidden-accessible");(a=this.element.is(":checked"))&&this.buttonElement.addClass("ui-state-active");this.buttonElement.attr("aria-pressed",a)}else this.buttonElement=this.element}, -widget:function(){return this.buttonElement},destroy:function(){this.element.removeClass("ui-helper-hidden-accessible");this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html());this.hasTitle||this.buttonElement.removeAttr("title"); -b.Widget.prototype.destroy.call(this)},_setOption:function(a,c){b.Widget.prototype._setOption.apply(this,arguments);if(a==="disabled")c?this.element.propAttr("disabled",true):this.element.propAttr("disabled",false);else this._resetButton()},refresh:function(){var a=this.element.is(":disabled");a!==this.options.disabled&&this._setOption("disabled",a);if(this.type==="radio")k(this.element[0]).each(function(){b(this).is(":checked")?b(this).button("widget").addClass("ui-state-active").attr("aria-pressed", -"true"):b(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")});else if(this.type==="checkbox")this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false")},_resetButton:function(){if(this.type==="input")this.options.label&&this.element.val(this.options.label);else{var a=this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"), -c=b("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(a.empty()).text(),e=this.options.icons,f=e.primary&&e.secondary,d=[];if(e.primary||e.secondary){if(this.options.text)d.push("ui-button-text-icon"+(f?"s":e.primary?"-primary":"-secondary"));e.primary&&a.prepend("<span class='ui-button-icon-primary ui-icon "+e.primary+"'></span>");e.secondary&&a.append("<span class='ui-button-icon-secondary ui-icon "+e.secondary+"'></span>");if(!this.options.text){d.push(f?"ui-button-icons-only": -"ui-button-icon-only");this.hasTitle||a.attr("title",c)}}else d.push("ui-button-text-only");a.addClass(d.join(" "))}}});b.widget("ui.buttonset",{options:{items:":button, :submit, :reset, :checkbox, :radio, a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(a,c){a==="disabled"&&this.buttons.button("option",a,c);b.Widget.prototype._setOption.apply(this,arguments)},refresh:function(){var a=this.element.css("direction")=== -"ltr";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(a?"ui-corner-left":"ui-corner-right").end().filter(":last").addClass(a?"ui-corner-right":"ui-corner-left").end().end()},destroy:function(){this.element.removeClass("ui-buttonset");this.buttons.map(function(){return b(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); -b.Widget.prototype.destroy.call(this)}})})(jQuery); -;/* - * jQuery UI Dialog 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Dialog - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - * jquery.ui.button.js - * jquery.ui.draggable.js - * jquery.ui.mouse.js - * jquery.ui.position.js - * jquery.ui.resizable.js - */ -(function(c,l){var m={buttons:true,height:true,maxHeight:true,maxWidth:true,minHeight:true,minWidth:true,width:true},n={maxHeight:true,maxWidth:true,minHeight:true,minWidth:true},o=c.attrFn||{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true,click:true};c.widget("ui.dialog",{options:{autoOpen:true,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false, -position:{my:"center",at:"center",collision:"fit",using:function(a){var b=c(this).css(a).offset().top;b<0&&c(this).css("top",a.top-b)}},resizable:true,show:null,stack:true,title:"",width:300,zIndex:1E3},_create:function(){this.originalTitle=this.element.attr("title");if(typeof this.originalTitle!=="string")this.originalTitle="";this.options.title=this.options.title||this.originalTitle;var a=this,b=a.options,d=b.title||" ",e=c.ui.dialog.getTitleId(a.element),g=(a.uiDialog=c("<div></div>")).appendTo(document.body).hide().addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+ -b.dialogClass).css({zIndex:b.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(i){if(b.closeOnEscape&&i.keyCode&&i.keyCode===c.ui.keyCode.ESCAPE){a.close(i);i.preventDefault()}}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(i){a.moveToTop(false,i)});a.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(g);var f=(a.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(g), -h=c('<a href="#"></a>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){h.addClass("ui-state-hover")},function(){h.removeClass("ui-state-hover")}).focus(function(){h.addClass("ui-state-focus")}).blur(function(){h.removeClass("ui-state-focus")}).click(function(i){a.close(i);return false}).appendTo(f);(a.uiDialogTitlebarCloseText=c("<span></span>")).addClass("ui-icon ui-icon-closethick").text(b.closeText).appendTo(h);c("<span></span>").addClass("ui-dialog-title").attr("id", -e).html(d).prependTo(f);if(c.isFunction(b.beforeclose)&&!c.isFunction(b.beforeClose))b.beforeClose=b.beforeclose;f.find("*").add(f).disableSelection();b.draggable&&c.fn.draggable&&a._makeDraggable();b.resizable&&c.fn.resizable&&a._makeResizable();a._createButtons(b.buttons);a._isOpen=false;c.fn.bgiframe&&g.bgiframe()},_init:function(){this.options.autoOpen&&this.open()},destroy:function(){var a=this;a.overlay&&a.overlay.destroy();a.uiDialog.hide();a.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"); -a.uiDialog.remove();a.originalTitle&&a.element.attr("title",a.originalTitle);return a},widget:function(){return this.uiDialog},close:function(a){var b=this,d,e;if(false!==b._trigger("beforeClose",a)){b.overlay&&b.overlay.destroy();b.uiDialog.unbind("keypress.ui-dialog");b._isOpen=false;if(b.options.hide)b.uiDialog.hide(b.options.hide,function(){b._trigger("close",a)});else{b.uiDialog.hide();b._trigger("close",a)}c.ui.dialog.overlay.resize();if(b.options.modal){d=0;c(".ui-dialog").each(function(){if(this!== -b.uiDialog[0]){e=c(this).css("z-index");isNaN(e)||(d=Math.max(d,e))}});c.ui.dialog.maxZ=d}return b}},isOpen:function(){return this._isOpen},moveToTop:function(a,b){var d=this,e=d.options;if(e.modal&&!a||!e.stack&&!e.modal)return d._trigger("focus",b);if(e.zIndex>c.ui.dialog.maxZ)c.ui.dialog.maxZ=e.zIndex;if(d.overlay){c.ui.dialog.maxZ+=1;d.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=c.ui.dialog.maxZ)}a={scrollTop:d.element.scrollTop(),scrollLeft:d.element.scrollLeft()};c.ui.dialog.maxZ+=1; -d.uiDialog.css("z-index",c.ui.dialog.maxZ);d.element.attr(a);d._trigger("focus",b);return d},open:function(){if(!this._isOpen){var a=this,b=a.options,d=a.uiDialog;a.overlay=b.modal?new c.ui.dialog.overlay(a):null;a._size();a._position(b.position);d.show(b.show);a.moveToTop(true);b.modal&&d.bind("keypress.ui-dialog",function(e){if(e.keyCode===c.ui.keyCode.TAB){var g=c(":tabbable",this),f=g.filter(":first");g=g.filter(":last");if(e.target===g[0]&&!e.shiftKey){f.focus(1);return false}else if(e.target=== -f[0]&&e.shiftKey){g.focus(1);return false}}});c(a.element.find(":tabbable").get().concat(d.find(".ui-dialog-buttonpane :tabbable").get().concat(d.get()))).eq(0).focus();a._isOpen=true;a._trigger("open");return a}},_createButtons:function(a){var b=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),g=c("<div></div>").addClass("ui-dialog-buttonset").appendTo(e);b.uiDialog.find(".ui-dialog-buttonpane").remove();typeof a==="object"&&a!==null&&c.each(a, -function(){return!(d=true)});if(d){c.each(a,function(f,h){h=c.isFunction(h)?{click:h,text:f}:h;var i=c('<button type="button"></button>').click(function(){h.click.apply(b.element[0],arguments)}).appendTo(g);c.each(h,function(j,k){if(j!=="click")j in o?i[j](k):i.attr(j,k)});c.fn.button&&i.button()});e.appendTo(b.uiDialog)}},_makeDraggable:function(){function a(f){return{position:f.position,offset:f.offset}}var b=this,d=b.options,e=c(document),g;b.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close", -handle:".ui-dialog-titlebar",containment:"document",start:function(f,h){g=d.height==="auto"?"auto":c(this).height();c(this).height(c(this).height()).addClass("ui-dialog-dragging");b._trigger("dragStart",f,a(h))},drag:function(f,h){b._trigger("drag",f,a(h))},stop:function(f,h){d.position=[h.position.left-e.scrollLeft(),h.position.top-e.scrollTop()];c(this).removeClass("ui-dialog-dragging").height(g);b._trigger("dragStop",f,a(h));c.ui.dialog.overlay.resize()}})},_makeResizable:function(a){function b(f){return{originalPosition:f.originalPosition, -originalSize:f.originalSize,position:f.position,size:f.size}}a=a===l?this.options.resizable:a;var d=this,e=d.options,g=d.uiDialog.css("position");a=typeof a==="string"?a:"n,e,s,w,se,sw,ne,nw";d.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:d.element,maxWidth:e.maxWidth,maxHeight:e.maxHeight,minWidth:e.minWidth,minHeight:d._minHeight(),handles:a,start:function(f,h){c(this).addClass("ui-dialog-resizing");d._trigger("resizeStart",f,b(h))},resize:function(f,h){d._trigger("resize", -f,b(h))},stop:function(f,h){c(this).removeClass("ui-dialog-resizing");e.height=c(this).height();e.width=c(this).width();d._trigger("resizeStop",f,b(h));c.ui.dialog.overlay.resize()}}).css("position",g).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var a=this.options;return a.height==="auto"?a.minHeight:Math.min(a.minHeight,a.height)},_position:function(a){var b=[],d=[0,0],e;if(a){if(typeof a==="string"||typeof a==="object"&&"0"in a){b=a.split?a.split(" "): -[a[0],a[1]];if(b.length===1)b[1]=b[0];c.each(["left","top"],function(g,f){if(+b[g]===b[g]){d[g]=b[g];b[g]=f}});a={my:b.join(" "),at:b.join(" "),offset:d.join(" ")}}a=c.extend({},c.ui.dialog.prototype.options.position,a)}else a=c.ui.dialog.prototype.options.position;(e=this.uiDialog.is(":visible"))||this.uiDialog.show();this.uiDialog.css({top:0,left:0}).position(c.extend({of:window},a));e||this.uiDialog.hide()},_setOptions:function(a){var b=this,d={},e=false;c.each(a,function(g,f){b._setOption(g,f); -if(g in m)e=true;if(g in n)d[g]=f});e&&this._size();this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",d)},_setOption:function(a,b){var d=this,e=d.uiDialog;switch(a){case "beforeclose":a="beforeClose";break;case "buttons":d._createButtons(b);break;case "closeText":d.uiDialogTitlebarCloseText.text(""+b);break;case "dialogClass":e.removeClass(d.options.dialogClass).addClass("ui-dialog ui-widget ui-widget-content ui-corner-all "+b);break;case "disabled":b?e.addClass("ui-dialog-disabled"): -e.removeClass("ui-dialog-disabled");break;case "draggable":var g=e.is(":data(draggable)");g&&!b&&e.draggable("destroy");!g&&b&&d._makeDraggable();break;case "position":d._position(b);break;case "resizable":(g=e.is(":data(resizable)"))&&!b&&e.resizable("destroy");g&&typeof b==="string"&&e.resizable("option","handles",b);!g&&b!==false&&d._makeResizable(b);break;case "title":c(".ui-dialog-title",d.uiDialogTitlebar).html(""+(b||" "));break}c.Widget.prototype._setOption.apply(d,arguments)},_size:function(){var a= -this.options,b,d,e=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0});if(a.minWidth>a.width)a.width=a.minWidth;b=this.uiDialog.css({height:"auto",width:a.width}).height();d=Math.max(0,a.minHeight-b);if(a.height==="auto")if(c.support.minHeight)this.element.css({minHeight:d,height:"auto"});else{this.uiDialog.show();a=this.element.css("height","auto").height();e||this.uiDialog.hide();this.element.height(Math.max(a,d))}else this.element.height(Math.max(a.height- -b,0));this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}});c.extend(c.ui.dialog,{version:"1.8.15",uuid:0,maxZ:0,getTitleId:function(a){a=a.attr("id");if(!a){this.uuid+=1;a=this.uuid}return"ui-dialog-title-"+a},overlay:function(a){this.$el=c.ui.dialog.overlay.create(a)}});c.extend(c.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(a){return a+".dialog-overlay"}).join(" "), -create:function(a){if(this.instances.length===0){setTimeout(function(){c.ui.dialog.overlay.instances.length&&c(document).bind(c.ui.dialog.overlay.events,function(d){if(c(d.target).zIndex()<c.ui.dialog.overlay.maxZ)return false})},1);c(document).bind("keydown.dialog-overlay",function(d){if(a.options.closeOnEscape&&d.keyCode&&d.keyCode===c.ui.keyCode.ESCAPE){a.close(d);d.preventDefault()}});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var b=(this.oldInstances.pop()||c("<div></div>").addClass("ui-widget-overlay")).appendTo(document.body).css({width:this.width(), -height:this.height()});c.fn.bgiframe&&b.bgiframe();this.instances.push(b);return b},destroy:function(a){var b=c.inArray(a,this.instances);b!=-1&&this.oldInstances.push(this.instances.splice(b,1)[0]);this.instances.length===0&&c([document,window]).unbind(".dialog-overlay");a.remove();var d=0;c.each(this.instances,function(){d=Math.max(d,this.css("z-index"))});this.maxZ=d},height:function(){var a,b;if(c.browser.msie&&c.browser.version<7){a=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight); -b=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);return a<b?c(window).height()+"px":a+"px"}else return c(document).height()+"px"},width:function(){var a,b;if(c.browser.msie){a=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);b=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);return a<b?c(window).width()+"px":a+"px"}else return c(document).width()+"px"},resize:function(){var a=c([]);c.each(c.ui.dialog.overlay.instances,function(){a= -a.add(this)});a.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery); -;/* - * jQuery UI Slider 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Slider - * - * Depends: - * jquery.ui.core.js - * jquery.ui.mouse.js - * jquery.ui.widget.js - */ -(function(d){d.widget("ui.slider",d.ui.mouse,{widgetEventPrefix:"slide",options:{animate:false,distance:0,max:100,min:0,orientation:"horizontal",range:false,step:1,value:0,values:null},_create:function(){var a=this,b=this.options,c=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),f=b.values&&b.values.length||1,e=[];this._mouseSliding=this._keySliding=false;this._animateOff=true;this._handleIndex=null;this._detectOrientation();this._mouseInit();this.element.addClass("ui-slider ui-slider-"+ -this.orientation+" ui-widget ui-widget-content ui-corner-all"+(b.disabled?" ui-slider-disabled ui-disabled":""));this.range=d([]);if(b.range){if(b.range===true){if(!b.values)b.values=[this._valueMin(),this._valueMin()];if(b.values.length&&b.values.length!==2)b.values=[b.values[0],b.values[0]]}this.range=d("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(b.range==="min"||b.range==="max"?" ui-slider-range-"+b.range:""))}for(var j=c.length;j<f;j+=1)e.push("<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>"); -this.handles=c.add(d(e.join("")).appendTo(a.element));this.handle=this.handles.eq(0);this.handles.add(this.range).filter("a").click(function(g){g.preventDefault()}).hover(function(){b.disabled||d(this).addClass("ui-state-hover")},function(){d(this).removeClass("ui-state-hover")}).focus(function(){if(b.disabled)d(this).blur();else{d(".ui-slider .ui-state-focus").removeClass("ui-state-focus");d(this).addClass("ui-state-focus")}}).blur(function(){d(this).removeClass("ui-state-focus")});this.handles.each(function(g){d(this).data("index.ui-slider-handle", -g)});this.handles.keydown(function(g){var k=true,l=d(this).data("index.ui-slider-handle"),i,h,m;if(!a.options.disabled){switch(g.keyCode){case d.ui.keyCode.HOME:case d.ui.keyCode.END:case d.ui.keyCode.PAGE_UP:case d.ui.keyCode.PAGE_DOWN:case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:k=false;if(!a._keySliding){a._keySliding=true;d(this).addClass("ui-state-active");i=a._start(g,l);if(i===false)return}break}m=a.options.step;i=a.options.values&&a.options.values.length? -(h=a.values(l)):(h=a.value());switch(g.keyCode){case d.ui.keyCode.HOME:h=a._valueMin();break;case d.ui.keyCode.END:h=a._valueMax();break;case d.ui.keyCode.PAGE_UP:h=a._trimAlignValue(i+(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.PAGE_DOWN:h=a._trimAlignValue(i-(a._valueMax()-a._valueMin())/5);break;case d.ui.keyCode.UP:case d.ui.keyCode.RIGHT:if(i===a._valueMax())return;h=a._trimAlignValue(i+m);break;case d.ui.keyCode.DOWN:case d.ui.keyCode.LEFT:if(i===a._valueMin())return;h=a._trimAlignValue(i- -m);break}a._slide(g,l,h);return k}}).keyup(function(g){var k=d(this).data("index.ui-slider-handle");if(a._keySliding){a._keySliding=false;a._stop(g,k);a._change(g,k);d(this).removeClass("ui-state-active")}});this._refreshValue();this._animateOff=false},destroy:function(){this.handles.remove();this.range.remove();this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all").removeData("slider").unbind(".slider");this._mouseDestroy(); -return this},_mouseCapture:function(a){var b=this.options,c,f,e,j,g;if(b.disabled)return false;this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()};this.elementOffset=this.element.offset();c=this._normValueFromMouse({x:a.pageX,y:a.pageY});f=this._valueMax()-this._valueMin()+1;j=this;this.handles.each(function(k){var l=Math.abs(c-j.values(k));if(f>l){f=l;e=d(this);g=k}});if(b.range===true&&this.values(1)===b.min){g+=1;e=d(this.handles[g])}if(this._start(a,g)===false)return false; -this._mouseSliding=true;j._handleIndex=g;e.addClass("ui-state-active").focus();b=e.offset();this._clickOffset=!d(a.target).parents().andSelf().is(".ui-slider-handle")?{left:0,top:0}:{left:a.pageX-b.left-e.width()/2,top:a.pageY-b.top-e.height()/2-(parseInt(e.css("borderTopWidth"),10)||0)-(parseInt(e.css("borderBottomWidth"),10)||0)+(parseInt(e.css("marginTop"),10)||0)};this.handles.hasClass("ui-state-hover")||this._slide(a,g,c);return this._animateOff=true},_mouseStart:function(){return true},_mouseDrag:function(a){var b= -this._normValueFromMouse({x:a.pageX,y:a.pageY});this._slide(a,this._handleIndex,b);return false},_mouseStop:function(a){this.handles.removeClass("ui-state-active");this._mouseSliding=false;this._stop(a,this._handleIndex);this._change(a,this._handleIndex);this._clickOffset=this._handleIndex=null;return this._animateOff=false},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(a){var b;if(this.orientation==="horizontal"){b= -this.elementSize.width;a=a.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)}else{b=this.elementSize.height;a=a.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)}b=a/b;if(b>1)b=1;if(b<0)b=0;if(this.orientation==="vertical")b=1-b;a=this._valueMax()-this._valueMin();return this._trimAlignValue(this._valueMin()+b*a)},_start:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b); -c.values=this.values()}return this._trigger("start",a,c)},_slide:function(a,b,c){var f;if(this.options.values&&this.options.values.length){f=this.values(b?0:1);if(this.options.values.length===2&&this.options.range===true&&(b===0&&c>f||b===1&&c<f))c=f;if(c!==this.values(b)){f=this.values();f[b]=c;a=this._trigger("slide",a,{handle:this.handles[b],value:c,values:f});this.values(b?0:1);a!==false&&this.values(b,c,true)}}else if(c!==this.value()){a=this._trigger("slide",a,{handle:this.handles[b],value:c}); -a!==false&&this.value(c)}},_stop:function(a,b){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("stop",a,c)},_change:function(a,b){if(!this._keySliding&&!this._mouseSliding){var c={handle:this.handles[b],value:this.value()};if(this.options.values&&this.options.values.length){c.value=this.values(b);c.values=this.values()}this._trigger("change",a,c)}},value:function(a){if(arguments.length){this.options.value= -this._trimAlignValue(a);this._refreshValue();this._change(null,0)}else return this._value()},values:function(a,b){var c,f,e;if(arguments.length>1){this.options.values[a]=this._trimAlignValue(b);this._refreshValue();this._change(null,a)}else if(arguments.length)if(d.isArray(arguments[0])){c=this.options.values;f=arguments[0];for(e=0;e<c.length;e+=1){c[e]=this._trimAlignValue(f[e]);this._change(null,e)}this._refreshValue()}else return this.options.values&&this.options.values.length?this._values(a): -this.value();else return this._values()},_setOption:function(a,b){var c,f=0;if(d.isArray(this.options.values))f=this.options.values.length;d.Widget.prototype._setOption.apply(this,arguments);switch(a){case "disabled":if(b){this.handles.filter(".ui-state-focus").blur();this.handles.removeClass("ui-state-hover");this.handles.propAttr("disabled",true);this.element.addClass("ui-disabled")}else{this.handles.propAttr("disabled",false);this.element.removeClass("ui-disabled")}break;case "orientation":this._detectOrientation(); -this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation);this._refreshValue();break;case "value":this._animateOff=true;this._refreshValue();this._change(null,0);this._animateOff=false;break;case "values":this._animateOff=true;this._refreshValue();for(c=0;c<f;c+=1)this._change(null,c);this._animateOff=false;break}},_value:function(){var a=this.options.value;return a=this._trimAlignValue(a)},_values:function(a){var b,c;if(arguments.length){b=this.options.values[a]; -return b=this._trimAlignValue(b)}else{b=this.options.values.slice();for(c=0;c<b.length;c+=1)b[c]=this._trimAlignValue(b[c]);return b}},_trimAlignValue:function(a){if(a<=this._valueMin())return this._valueMin();if(a>=this._valueMax())return this._valueMax();var b=this.options.step>0?this.options.step:1,c=(a-this._valueMin())%b;a=a-c;if(Math.abs(c)*2>=b)a+=c>0?b:-b;return parseFloat(a.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var a= -this.options.range,b=this.options,c=this,f=!this._animateOff?b.animate:false,e,j={},g,k,l,i;if(this.options.values&&this.options.values.length)this.handles.each(function(h){e=(c.values(h)-c._valueMin())/(c._valueMax()-c._valueMin())*100;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";d(this).stop(1,1)[f?"animate":"css"](j,b.animate);if(c.options.range===true)if(c.orientation==="horizontal"){if(h===0)c.range.stop(1,1)[f?"animate":"css"]({left:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({width:e- -g+"%"},{queue:false,duration:b.animate})}else{if(h===0)c.range.stop(1,1)[f?"animate":"css"]({bottom:e+"%"},b.animate);if(h===1)c.range[f?"animate":"css"]({height:e-g+"%"},{queue:false,duration:b.animate})}g=e});else{k=this.value();l=this._valueMin();i=this._valueMax();e=i!==l?(k-l)/(i-l)*100:0;j[c.orientation==="horizontal"?"left":"bottom"]=e+"%";this.handle.stop(1,1)[f?"animate":"css"](j,b.animate);if(a==="min"&&this.orientation==="horizontal")this.range.stop(1,1)[f?"animate":"css"]({width:e+"%"}, -b.animate);if(a==="max"&&this.orientation==="horizontal")this.range[f?"animate":"css"]({width:100-e+"%"},{queue:false,duration:b.animate});if(a==="min"&&this.orientation==="vertical")this.range.stop(1,1)[f?"animate":"css"]({height:e+"%"},b.animate);if(a==="max"&&this.orientation==="vertical")this.range[f?"animate":"css"]({height:100-e+"%"},{queue:false,duration:b.animate})}}});d.extend(d.ui.slider,{version:"1.8.15"})})(jQuery); -;/* - * jQuery UI Tabs 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Tabs - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function(d,p){function u(){return++v}function w(){return++x}var v=0,x=0;d.widget("ui.tabs",{options:{add:null,ajaxOptions:null,cache:false,cookie:null,collapsible:false,disable:null,disabled:[],enable:null,event:"click",fx:null,idPrefix:"ui-tabs-",load:null,panelTemplate:"<div></div>",remove:null,select:null,show:null,spinner:"<em>Loading…</em>",tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},_create:function(){this._tabify(true)},_setOption:function(b,e){if(b=="selected")this.options.collapsible&& -e==this.options.selected||this.select(e);else{this.options[b]=e;this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF-]/g,"")||this.options.idPrefix+u()},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+w());return d.cookie.apply(null,[b].concat(d.makeArray(arguments)))},_ui:function(b,e){return{tab:b,panel:e,index:this.anchors.index(b)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b= -d(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(b){function e(g,f){g.css("display","");!d.support.opacity&&f.opacity&&g[0].style.removeAttribute("filter")}var a=this,c=this.options,h=/^#.+/;this.list=this.element.find("ol,ul").eq(0);this.lis=d(" > li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return d("a",this)[0]});this.panels=d([]);this.anchors.each(function(g,f){var i=d(f).attr("href"),l=i.split("#")[0],q;if(l&&(l===location.toString().split("#")[0]|| -(q=d("base")[0])&&l===q.href)){i=f.hash;f.href=i}if(h.test(i))a.panels=a.panels.add(a.element.find(a._sanitizeSelector(i)));else if(i&&i!=="#"){d.data(f,"href.tabs",i);d.data(f,"load.tabs",i.replace(/#.*$/,""));i=a._tabId(f);f.href="#"+i;f=a.element.find("#"+i);if(!f.length){f=d(c.panelTemplate).attr("id",i).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(a.panels[g-1]||a.list);f.data("destroy.tabs",true)}a.panels=a.panels.add(f)}else c.disabled.push(g)});if(b){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all"); -this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(c.selected===p){location.hash&&this.anchors.each(function(g,f){if(f.hash==location.hash){c.selected=g;return false}});if(typeof c.selected!=="number"&&c.cookie)c.selected=parseInt(a._cookie(),10);if(typeof c.selected!=="number"&&this.lis.filter(".ui-tabs-selected").length)c.selected= -this.lis.index(this.lis.filter(".ui-tabs-selected"));c.selected=c.selected||(this.lis.length?0:-1)}else if(c.selected===null)c.selected=-1;c.selected=c.selected>=0&&this.anchors[c.selected]||c.selected<0?c.selected:0;c.disabled=d.unique(c.disabled.concat(d.map(this.lis.filter(".ui-state-disabled"),function(g){return a.lis.index(g)}))).sort();d.inArray(c.selected,c.disabled)!=-1&&c.disabled.splice(d.inArray(c.selected,c.disabled),1);this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active"); -if(c.selected>=0&&this.anchors.length){a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash)).removeClass("ui-tabs-hide");this.lis.eq(c.selected).addClass("ui-tabs-selected ui-state-active");a.element.queue("tabs",function(){a._trigger("show",null,a._ui(a.anchors[c.selected],a.element.find(a._sanitizeSelector(a.anchors[c.selected].hash))[0]))});this.load(c.selected)}d(window).bind("unload",function(){a.lis.add(a.anchors).unbind(".tabs");a.lis=a.anchors=a.panels=null})}else c.selected=this.lis.index(this.lis.filter(".ui-tabs-selected")); -this.element[c.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");c.cookie&&this._cookie(c.selected,c.cookie);b=0;for(var j;j=this.lis[b];b++)d(j)[d.inArray(b,c.disabled)!=-1&&!d(j).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled");c.cache===false&&this.anchors.removeData("cache.tabs");this.lis.add(this.anchors).unbind(".tabs");if(c.event!=="mouseover"){var k=function(g,f){f.is(":not(.ui-state-disabled)")&&f.addClass("ui-state-"+g)},n=function(g,f){f.removeClass("ui-state-"+ -g)};this.lis.bind("mouseover.tabs",function(){k("hover",d(this))});this.lis.bind("mouseout.tabs",function(){n("hover",d(this))});this.anchors.bind("focus.tabs",function(){k("focus",d(this).closest("li"))});this.anchors.bind("blur.tabs",function(){n("focus",d(this).closest("li"))})}var m,o;if(c.fx)if(d.isArray(c.fx)){m=c.fx[0];o=c.fx[1]}else m=o=c.fx;var r=o?function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.hide().removeClass("ui-tabs-hide").animate(o,o.duration||"normal", -function(){e(f,o);a._trigger("show",null,a._ui(g,f[0]))})}:function(g,f){d(g).closest("li").addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");a._trigger("show",null,a._ui(g,f[0]))},s=m?function(g,f){f.animate(m,m.duration||"normal",function(){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");e(f,m);a.element.dequeue("tabs")})}:function(g,f){a.lis.removeClass("ui-tabs-selected ui-state-active");f.addClass("ui-tabs-hide");a.element.dequeue("tabs")}; -this.anchors.bind(c.event+".tabs",function(){var g=this,f=d(g).closest("li"),i=a.panels.filter(":not(.ui-tabs-hide)"),l=a.element.find(a._sanitizeSelector(g.hash));if(f.hasClass("ui-tabs-selected")&&!c.collapsible||f.hasClass("ui-state-disabled")||f.hasClass("ui-state-processing")||a.panels.filter(":animated").length||a._trigger("select",null,a._ui(this,l[0]))===false){this.blur();return false}c.selected=a.anchors.index(this);a.abort();if(c.collapsible)if(f.hasClass("ui-tabs-selected")){c.selected= --1;c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){s(g,i)}).dequeue("tabs");this.blur();return false}else if(!i.length){c.cookie&&a._cookie(c.selected,c.cookie);a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this));this.blur();return false}c.cookie&&a._cookie(c.selected,c.cookie);if(l.length){i.length&&a.element.queue("tabs",function(){s(g,i)});a.element.queue("tabs",function(){r(g,l)});a.load(a.anchors.index(this))}else throw"jQuery UI Tabs: Mismatching fragment identifier."; -d.browser.msie&&this.blur()});this.anchors.bind("click.tabs",function(){return false})},_getIndex:function(b){if(typeof b=="string")b=this.anchors.index(this.anchors.filter("[href$="+b+"]"));return b},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var e= -d.data(this,"href.tabs");if(e)this.href=e;var a=d(this).unbind(".tabs");d.each(["href","load","cache"],function(c,h){a.removeData(h+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){d.data(this,"destroy.tabs")?d(this).remove():d(this).removeClass("ui-state-default ui-corner-top ui-tabs-selected ui-state-active ui-state-hover ui-state-focus ui-state-disabled ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide")});b.cookie&&this._cookie(null,b.cookie);return this},add:function(b, -e,a){if(a===p)a=this.anchors.length;var c=this,h=this.options;e=d(h.tabTemplate.replace(/#\{href\}/g,b).replace(/#\{label\}/g,e));b=!b.indexOf("#")?b.replace("#",""):this._tabId(d("a",e)[0]);e.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var j=c.element.find("#"+b);j.length||(j=d(h.panelTemplate).attr("id",b).data("destroy.tabs",true));j.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(a>=this.lis.length){e.appendTo(this.list);j.appendTo(this.list[0].parentNode)}else{e.insertBefore(this.lis[a]); -j.insertBefore(this.panels[a])}h.disabled=d.map(h.disabled,function(k){return k>=a?++k:k});this._tabify();if(this.anchors.length==1){h.selected=0;e.addClass("ui-tabs-selected ui-state-active");j.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){c._trigger("show",null,c._ui(c.anchors[0],c.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[a],this.panels[a]));return this},remove:function(b){b=this._getIndex(b);var e=this.options,a=this.lis.eq(b).remove(),c=this.panels.eq(b).remove(); -if(a.hasClass("ui-tabs-selected")&&this.anchors.length>1)this.select(b+(b+1<this.anchors.length?1:-1));e.disabled=d.map(d.grep(e.disabled,function(h){return h!=b}),function(h){return h>=b?--h:h});this._tabify();this._trigger("remove",null,this._ui(a.find("a")[0],c[0]));return this},enable:function(b){b=this._getIndex(b);var e=this.options;if(d.inArray(b,e.disabled)!=-1){this.lis.eq(b).removeClass("ui-state-disabled");e.disabled=d.grep(e.disabled,function(a){return a!=b});this._trigger("enable",null, -this._ui(this.anchors[b],this.panels[b]));return this}},disable:function(b){b=this._getIndex(b);var e=this.options;if(b!=e.selected){this.lis.eq(b).addClass("ui-state-disabled");e.disabled.push(b);e.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[b],this.panels[b]))}return this},select:function(b){b=this._getIndex(b);if(b==-1)if(this.options.collapsible&&this.options.selected!=-1)b=this.options.selected;else return this;this.anchors.eq(b).trigger(this.options.event+".tabs");return this}, -load:function(b){b=this._getIndex(b);var e=this,a=this.options,c=this.anchors.eq(b)[0],h=d.data(c,"load.tabs");this.abort();if(!h||this.element.queue("tabs").length!==0&&d.data(c,"cache.tabs"))this.element.dequeue("tabs");else{this.lis.eq(b).addClass("ui-state-processing");if(a.spinner){var j=d("span",c);j.data("label.tabs",j.html()).html(a.spinner)}this.xhr=d.ajax(d.extend({},a.ajaxOptions,{url:h,success:function(k,n){e.element.find(e._sanitizeSelector(c.hash)).html(k);e._cleanup();a.cache&&d.data(c, -"cache.tabs",true);e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.success(k,n)}catch(m){}},error:function(k,n){e._cleanup();e._trigger("load",null,e._ui(e.anchors[b],e.panels[b]));try{a.ajaxOptions.error(k,n,b,c)}catch(m){}}}));e.element.dequeue("tabs");return this}},abort:function(){this.element.queue([]);this.panels.stop(false,true);this.element.queue("tabs",this.element.queue("tabs").splice(-2,2));if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup();return this}, -url:function(b,e){this.anchors.eq(b).removeData("cache.tabs").data("load.tabs",e);return this},length:function(){return this.anchors.length}});d.extend(d.ui.tabs,{version:"1.8.15"});d.extend(d.ui.tabs.prototype,{rotation:null,rotate:function(b,e){var a=this,c=this.options,h=a._rotate||(a._rotate=function(j){clearTimeout(a.rotation);a.rotation=setTimeout(function(){var k=c.selected;a.select(++k<a.anchors.length?k:0)},b);j&&j.stopPropagation()});e=a._unrotate||(a._unrotate=!e?function(j){j.clientX&& -a.rotate(null)}:function(){t=c.selected;h()});if(b){this.element.bind("tabsshow",h);this.anchors.bind(c.event+".tabs",e);h()}else{clearTimeout(a.rotation);this.element.unbind("tabsshow",h);this.anchors.unbind(c.event+".tabs",e);delete this._rotate;delete this._unrotate}return this}})})(jQuery); -;/* - * jQuery UI Datepicker 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Datepicker - * - * Depends: - * jquery.ui.core.js - */ -(function(d,C){function M(){this.debug=false;this._curInst=null;this._keyEvent=false;this._disabledInputs=[];this._inDialog=this._datepickerShowing=false;this._mainDivId="ui-datepicker-div";this._inlineClass="ui-datepicker-inline";this._appendClass="ui-datepicker-append";this._triggerClass="ui-datepicker-trigger";this._dialogClass="ui-datepicker-dialog";this._disableClass="ui-datepicker-disabled";this._unselectableClass="ui-datepicker-unselectable";this._currentClass="ui-datepicker-current-day";this._dayOverClass= -"ui-datepicker-days-cell-over";this.regional=[];this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su", -"Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:false,showMonthAfterYear:false,yearSuffix:""};this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:false,hideIfNoPrevNext:false,navigationAsDateFormat:false,gotoCurrent:false,changeMonth:false,changeYear:false,yearRange:"c-10:c+10",showOtherMonths:false,selectOtherMonths:false,showWeek:false,calculateWeek:this.iso8601Week,shortYearCutoff:"+10", -minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:true,showButtonPanel:false,autoSize:false,disabled:false};d.extend(this._defaults,this.regional[""]);this.dpDiv=N(d('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}function N(a){return a.bind("mouseout", -function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");b.length&&b.removeClass("ui-state-hover ui-datepicker-prev-hover ui-datepicker-next-hover")}).bind("mouseover",function(b){b=d(b.target).closest("button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a");if(!(d.datepicker._isDisabledDatepicker(J.inline?a.parent()[0]:J.input[0])||!b.length)){b.parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"); -b.addClass("ui-state-hover");b.hasClass("ui-datepicker-prev")&&b.addClass("ui-datepicker-prev-hover");b.hasClass("ui-datepicker-next")&&b.addClass("ui-datepicker-next-hover")}})}function H(a,b){d.extend(a,b);for(var c in b)if(b[c]==null||b[c]==C)a[c]=b[c];return a}d.extend(d.ui,{datepicker:{version:"1.8.15"}});var B=(new Date).getTime(),J;d.extend(M.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv}, -setDefaults:function(a){H(this._defaults,a||{});return this},_attachDatepicker:function(a,b){var c=null;for(var e in this._defaults){var f=a.getAttribute("date:"+e);if(f){c=c||{};try{c[e]=eval(f)}catch(h){c[e]=f}}}e=a.nodeName.toLowerCase();f=e=="div"||e=="span";if(!a.id){this.uuid+=1;a.id="dp"+this.uuid}var i=this._newInst(d(a),f);i.settings=d.extend({},b||{},c||{});if(e=="input")this._connectDatepicker(a,i);else f&&this._inlineDatepicker(a,i)},_newInst:function(a,b){return{id:a[0].id.replace(/([^A-Za-z0-9_-])/g, -"\\\\$1"),input:a,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:b,dpDiv:!b?this.dpDiv:N(d('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}},_connectDatepicker:function(a,b){var c=d(a);b.append=d([]);b.trigger=d([]);if(!c.hasClass(this.markerClassName)){this._attachments(c,b);c.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker", -function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});this._autoSize(b);d.data(a,"datepicker",b);b.settings.disabled&&this._disableDatepicker(a)}},_attachments:function(a,b){var c=this._get(b,"appendText"),e=this._get(b,"isRTL");b.append&&b.append.remove();if(c){b.append=d('<span class="'+this._appendClass+'">'+c+"</span>");a[e?"before":"after"](b.append)}a.unbind("focus",this._showDatepicker);b.trigger&&b.trigger.remove();c=this._get(b,"showOn");if(c== -"focus"||c=="both")a.focus(this._showDatepicker);if(c=="button"||c=="both"){c=this._get(b,"buttonText");var f=this._get(b,"buttonImage");b.trigger=d(this._get(b,"buttonImageOnly")?d("<img/>").addClass(this._triggerClass).attr({src:f,alt:c,title:c}):d('<button type="button"></button>').addClass(this._triggerClass).html(f==""?c:d("<img/>").attr({src:f,alt:c,title:c})));a[e?"before":"after"](b.trigger);b.trigger.click(function(){d.datepicker._datepickerShowing&&d.datepicker._lastInput==a[0]?d.datepicker._hideDatepicker(): -d.datepicker._showDatepicker(a[0]);return false})}},_autoSize:function(a){if(this._get(a,"autoSize")&&!a.inline){var b=new Date(2009,11,20),c=this._get(a,"dateFormat");if(c.match(/[DM]/)){var e=function(f){for(var h=0,i=0,g=0;g<f.length;g++)if(f[g].length>h){h=f[g].length;i=g}return i};b.setMonth(e(this._get(a,c.match(/MM/)?"monthNames":"monthNamesShort")));b.setDate(e(this._get(a,c.match(/DD/)?"dayNames":"dayNamesShort"))+20-b.getDay())}a.input.attr("size",this._formatDate(a,b).length)}},_inlineDatepicker:function(a, -b){var c=d(a);if(!c.hasClass(this.markerClassName)){c.addClass(this.markerClassName).append(b.dpDiv).bind("setData.datepicker",function(e,f,h){b.settings[f]=h}).bind("getData.datepicker",function(e,f){return this._get(b,f)});d.data(a,"datepicker",b);this._setDate(b,this._getDefaultDate(b),true);this._updateDatepicker(b);this._updateAlternate(b);b.settings.disabled&&this._disableDatepicker(a);b.dpDiv.css("display","block")}},_dialogDatepicker:function(a,b,c,e,f){a=this._dialogInst;if(!a){this.uuid+= -1;this._dialogInput=d('<input type="text" id="'+("dp"+this.uuid)+'" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');this._dialogInput.keydown(this._doKeyDown);d("body").append(this._dialogInput);a=this._dialogInst=this._newInst(this._dialogInput,false);a.settings={};d.data(this._dialogInput[0],"datepicker",a)}H(a.settings,e||{});b=b&&b.constructor==Date?this._formatDate(a,b):b;this._dialogInput.val(b);this._pos=f?f.length?f:[f.pageX,f.pageY]:null;if(!this._pos)this._pos=[document.documentElement.clientWidth/ -2-100+(document.documentElement.scrollLeft||document.body.scrollLeft),document.documentElement.clientHeight/2-150+(document.documentElement.scrollTop||document.body.scrollTop)];this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px");a.settings.onSelect=c;this._inDialog=true;this.dpDiv.addClass(this._dialogClass);this._showDatepicker(this._dialogInput[0]);d.blockUI&&d.blockUI(this.dpDiv);d.data(this._dialogInput[0],"datepicker",a);return this},_destroyDatepicker:function(a){var b= -d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();d.removeData(a,"datepicker");if(e=="input"){c.append.remove();c.trigger.remove();b.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)}else if(e=="div"||e=="span")b.removeClass(this.markerClassName).empty()}},_enableDatepicker:function(a){var b=d(a),c=d.data(a,"datepicker");if(b.hasClass(this.markerClassName)){var e= -a.nodeName.toLowerCase();if(e=="input"){a.disabled=false;c.trigger.filter("button").each(function(){this.disabled=false}).end().filter("img").css({opacity:"1.0",cursor:""})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().removeClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").removeAttr("disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f==a?null:f})}},_disableDatepicker:function(a){var b=d(a),c=d.data(a, -"datepicker");if(b.hasClass(this.markerClassName)){var e=a.nodeName.toLowerCase();if(e=="input"){a.disabled=true;c.trigger.filter("button").each(function(){this.disabled=true}).end().filter("img").css({opacity:"0.5",cursor:"default"})}else if(e=="div"||e=="span"){b=b.children("."+this._inlineClass);b.children().addClass("ui-state-disabled");b.find("select.ui-datepicker-month, select.ui-datepicker-year").attr("disabled","disabled")}this._disabledInputs=d.map(this._disabledInputs,function(f){return f== -a?null:f});this._disabledInputs[this._disabledInputs.length]=a}},_isDisabledDatepicker:function(a){if(!a)return false;for(var b=0;b<this._disabledInputs.length;b++)if(this._disabledInputs[b]==a)return true;return false},_getInst:function(a){try{return d.data(a,"datepicker")}catch(b){throw"Missing instance data for this datepicker";}},_optionDatepicker:function(a,b,c){var e=this._getInst(a);if(arguments.length==2&&typeof b=="string")return b=="defaults"?d.extend({},d.datepicker._defaults):e?b=="all"? -d.extend({},e.settings):this._get(e,b):null;var f=b||{};if(typeof b=="string"){f={};f[b]=c}if(e){this._curInst==e&&this._hideDatepicker();var h=this._getDateDatepicker(a,true),i=this._getMinMaxDate(e,"min"),g=this._getMinMaxDate(e,"max");H(e.settings,f);if(i!==null&&f.dateFormat!==C&&f.minDate===C)e.settings.minDate=this._formatDate(e,i);if(g!==null&&f.dateFormat!==C&&f.maxDate===C)e.settings.maxDate=this._formatDate(e,g);this._attachments(d(a),e);this._autoSize(e);this._setDate(e,h);this._updateAlternate(e); -this._updateDatepicker(e)}},_changeDatepicker:function(a,b,c){this._optionDatepicker(a,b,c)},_refreshDatepicker:function(a){(a=this._getInst(a))&&this._updateDatepicker(a)},_setDateDatepicker:function(a,b){if(a=this._getInst(a)){this._setDate(a,b);this._updateDatepicker(a);this._updateAlternate(a)}},_getDateDatepicker:function(a,b){(a=this._getInst(a))&&!a.inline&&this._setDateFromField(a,b);return a?this._getDate(a):null},_doKeyDown:function(a){var b=d.datepicker._getInst(a.target),c=true,e=b.dpDiv.is(".ui-datepicker-rtl"); -b._keyEvent=true;if(d.datepicker._datepickerShowing)switch(a.keyCode){case 9:d.datepicker._hideDatepicker();c=false;break;case 13:c=d("td."+d.datepicker._dayOverClass+":not(."+d.datepicker._currentClass+")",b.dpDiv);c[0]&&d.datepicker._selectDay(a.target,b.selectedMonth,b.selectedYear,c[0]);if(a=d.datepicker._get(b,"onSelect")){c=d.datepicker._formatDate(b);a.apply(b.input?b.input[0]:null,[c,b])}else d.datepicker._hideDatepicker();return false;case 27:d.datepicker._hideDatepicker();break;case 33:d.datepicker._adjustDate(a.target, -a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 34:d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b,"stepMonths"),"M");break;case 35:if(a.ctrlKey||a.metaKey)d.datepicker._clearDate(a.target);c=a.ctrlKey||a.metaKey;break;case 36:if(a.ctrlKey||a.metaKey)d.datepicker._gotoToday(a.target);c=a.ctrlKey||a.metaKey;break;case 37:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?+1:-1,"D");c= -a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?-d.datepicker._get(b,"stepBigMonths"):-d.datepicker._get(b,"stepMonths"),"M");break;case 38:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,-7,"D");c=a.ctrlKey||a.metaKey;break;case 39:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,e?-1:+1,"D");c=a.ctrlKey||a.metaKey;if(a.originalEvent.altKey)d.datepicker._adjustDate(a.target,a.ctrlKey?+d.datepicker._get(b,"stepBigMonths"):+d.datepicker._get(b, -"stepMonths"),"M");break;case 40:if(a.ctrlKey||a.metaKey)d.datepicker._adjustDate(a.target,+7,"D");c=a.ctrlKey||a.metaKey;break;default:c=false}else if(a.keyCode==36&&a.ctrlKey)d.datepicker._showDatepicker(this);else c=false;if(c){a.preventDefault();a.stopPropagation()}},_doKeyPress:function(a){var b=d.datepicker._getInst(a.target);if(d.datepicker._get(b,"constrainInput")){b=d.datepicker._possibleChars(d.datepicker._get(b,"dateFormat"));var c=String.fromCharCode(a.charCode==C?a.keyCode:a.charCode); -return a.ctrlKey||a.metaKey||c<" "||!b||b.indexOf(c)>-1}},_doKeyUp:function(a){a=d.datepicker._getInst(a.target);if(a.input.val()!=a.lastVal)try{if(d.datepicker.parseDate(d.datepicker._get(a,"dateFormat"),a.input?a.input.val():null,d.datepicker._getFormatConfig(a))){d.datepicker._setDateFromField(a);d.datepicker._updateAlternate(a);d.datepicker._updateDatepicker(a)}}catch(b){d.datepicker.log(b)}return true},_showDatepicker:function(a){a=a.target||a;if(a.nodeName.toLowerCase()!="input")a=d("input", -a.parentNode)[0];if(!(d.datepicker._isDisabledDatepicker(a)||d.datepicker._lastInput==a)){var b=d.datepicker._getInst(a);if(d.datepicker._curInst&&d.datepicker._curInst!=b){d.datepicker._datepickerShowing&&d.datepicker._triggerOnClose(d.datepicker._curInst);d.datepicker._curInst.dpDiv.stop(true,true)}var c=d.datepicker._get(b,"beforeShow");H(b.settings,c?c.apply(a,[a,b]):{});b.lastVal=null;d.datepicker._lastInput=a;d.datepicker._setDateFromField(b);if(d.datepicker._inDialog)a.value="";if(!d.datepicker._pos){d.datepicker._pos= -d.datepicker._findPos(a);d.datepicker._pos[1]+=a.offsetHeight}var e=false;d(a).parents().each(function(){e|=d(this).css("position")=="fixed";return!e});if(e&&d.browser.opera){d.datepicker._pos[0]-=document.documentElement.scrollLeft;d.datepicker._pos[1]-=document.documentElement.scrollTop}c={left:d.datepicker._pos[0],top:d.datepicker._pos[1]};d.datepicker._pos=null;b.dpDiv.empty();b.dpDiv.css({position:"absolute",display:"block",top:"-1000px"});d.datepicker._updateDatepicker(b);c=d.datepicker._checkOffset(b, -c,e);b.dpDiv.css({position:d.datepicker._inDialog&&d.blockUI?"static":e?"fixed":"absolute",display:"none",left:c.left+"px",top:c.top+"px"});if(!b.inline){c=d.datepicker._get(b,"showAnim");var f=d.datepicker._get(b,"duration"),h=function(){var i=b.dpDiv.find("iframe.ui-datepicker-cover");if(i.length){var g=d.datepicker._getBorders(b.dpDiv);i.css({left:-g[0],top:-g[1],width:b.dpDiv.outerWidth(),height:b.dpDiv.outerHeight()})}};b.dpDiv.zIndex(d(a).zIndex()+1);d.datepicker._datepickerShowing=true;d.effects&& -d.effects[c]?b.dpDiv.show(c,d.datepicker._get(b,"showOptions"),f,h):b.dpDiv[c||"show"](c?f:null,h);if(!c||!f)h();b.input.is(":visible")&&!b.input.is(":disabled")&&b.input.focus();d.datepicker._curInst=b}}},_updateDatepicker:function(a){this.maxRows=4;var b=d.datepicker._getBorders(a.dpDiv);J=a;a.dpDiv.empty().append(this._generateHTML(a));var c=a.dpDiv.find("iframe.ui-datepicker-cover");c.length&&c.css({left:-b[0],top:-b[1],width:a.dpDiv.outerWidth(),height:a.dpDiv.outerHeight()});a.dpDiv.find("."+ -this._dayOverClass+" a").mouseover();b=this._getNumberOfMonths(a);c=b[1];a.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");c>1&&a.dpDiv.addClass("ui-datepicker-multi-"+c).css("width",17*c+"em");a.dpDiv[(b[0]!=1||b[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi");a.dpDiv[(this._get(a,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl");a==d.datepicker._curInst&&d.datepicker._datepickerShowing&&a.input&&a.input.is(":visible")&&!a.input.is(":disabled")&& -a.input[0]!=document.activeElement&&a.input.focus();if(a.yearshtml){var e=a.yearshtml;setTimeout(function(){e===a.yearshtml&&a.yearshtml&&a.dpDiv.find("select.ui-datepicker-year:first").replaceWith(a.yearshtml);e=a.yearshtml=null},0)}},_getBorders:function(a){var b=function(c){return{thin:1,medium:2,thick:3}[c]||c};return[parseFloat(b(a.css("border-left-width"))),parseFloat(b(a.css("border-top-width")))]},_checkOffset:function(a,b,c){var e=a.dpDiv.outerWidth(),f=a.dpDiv.outerHeight(),h=a.input?a.input.outerWidth(): -0,i=a.input?a.input.outerHeight():0,g=document.documentElement.clientWidth+d(document).scrollLeft(),j=document.documentElement.clientHeight+d(document).scrollTop();b.left-=this._get(a,"isRTL")?e-h:0;b.left-=c&&b.left==a.input.offset().left?d(document).scrollLeft():0;b.top-=c&&b.top==a.input.offset().top+i?d(document).scrollTop():0;b.left-=Math.min(b.left,b.left+e>g&&g>e?Math.abs(b.left+e-g):0);b.top-=Math.min(b.top,b.top+f>j&&j>f?Math.abs(f+i):0);return b},_findPos:function(a){for(var b=this._get(this._getInst(a), -"isRTL");a&&(a.type=="hidden"||a.nodeType!=1||d.expr.filters.hidden(a));)a=a[b?"previousSibling":"nextSibling"];a=d(a).offset();return[a.left,a.top]},_triggerOnClose:function(a){var b=this._get(a,"onClose");if(b)b.apply(a.input?a.input[0]:null,[a.input?a.input.val():"",a])},_hideDatepicker:function(a){var b=this._curInst;if(!(!b||a&&b!=d.data(a,"datepicker")))if(this._datepickerShowing){a=this._get(b,"showAnim");var c=this._get(b,"duration"),e=function(){d.datepicker._tidyDialog(b);this._curInst= -null};d.effects&&d.effects[a]?b.dpDiv.hide(a,d.datepicker._get(b,"showOptions"),c,e):b.dpDiv[a=="slideDown"?"slideUp":a=="fadeIn"?"fadeOut":"hide"](a?c:null,e);a||e();d.datepicker._triggerOnClose(b);this._datepickerShowing=false;this._lastInput=null;if(this._inDialog){this._dialogInput.css({position:"absolute",left:"0",top:"-100px"});if(d.blockUI){d.unblockUI();d("body").append(this.dpDiv)}}this._inDialog=false}},_tidyDialog:function(a){a.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")}, -_checkExternalClick:function(a){if(d.datepicker._curInst){a=d(a.target);a[0].id!=d.datepicker._mainDivId&&a.parents("#"+d.datepicker._mainDivId).length==0&&!a.hasClass(d.datepicker.markerClassName)&&!a.hasClass(d.datepicker._triggerClass)&&d.datepicker._datepickerShowing&&!(d.datepicker._inDialog&&d.blockUI)&&d.datepicker._hideDatepicker()}},_adjustDate:function(a,b,c){a=d(a);var e=this._getInst(a[0]);if(!this._isDisabledDatepicker(a[0])){this._adjustInstDate(e,b+(c=="M"?this._get(e,"showCurrentAtPos"): -0),c);this._updateDatepicker(e)}},_gotoToday:function(a){a=d(a);var b=this._getInst(a[0]);if(this._get(b,"gotoCurrent")&&b.currentDay){b.selectedDay=b.currentDay;b.drawMonth=b.selectedMonth=b.currentMonth;b.drawYear=b.selectedYear=b.currentYear}else{var c=new Date;b.selectedDay=c.getDate();b.drawMonth=b.selectedMonth=c.getMonth();b.drawYear=b.selectedYear=c.getFullYear()}this._notifyChange(b);this._adjustDate(a)},_selectMonthYear:function(a,b,c){a=d(a);var e=this._getInst(a[0]);e["selected"+(c=="M"? -"Month":"Year")]=e["draw"+(c=="M"?"Month":"Year")]=parseInt(b.options[b.selectedIndex].value,10);this._notifyChange(e);this._adjustDate(a)},_selectDay:function(a,b,c,e){var f=d(a);if(!(d(e).hasClass(this._unselectableClass)||this._isDisabledDatepicker(f[0]))){f=this._getInst(f[0]);f.selectedDay=f.currentDay=d("a",e).html();f.selectedMonth=f.currentMonth=b;f.selectedYear=f.currentYear=c;this._selectDate(a,this._formatDate(f,f.currentDay,f.currentMonth,f.currentYear))}},_clearDate:function(a){a=d(a); -this._getInst(a[0]);this._selectDate(a,"")},_selectDate:function(a,b){a=this._getInst(d(a)[0]);b=b!=null?b:this._formatDate(a);a.input&&a.input.val(b);this._updateAlternate(a);var c=this._get(a,"onSelect");if(c)c.apply(a.input?a.input[0]:null,[b,a]);else a.input&&a.input.trigger("change");if(a.inline)this._updateDatepicker(a);else{this._hideDatepicker();this._lastInput=a.input[0];a.input.focus();this._lastInput=null}},_updateAlternate:function(a){var b=this._get(a,"altField");if(b){var c=this._get(a, -"altFormat")||this._get(a,"dateFormat"),e=this._getDate(a),f=this.formatDate(c,e,this._getFormatConfig(a));d(b).each(function(){d(this).val(f)})}},noWeekends:function(a){a=a.getDay();return[a>0&&a<6,""]},iso8601Week:function(a){a=new Date(a.getTime());a.setDate(a.getDate()+4-(a.getDay()||7));var b=a.getTime();a.setMonth(0);a.setDate(1);return Math.floor(Math.round((b-a)/864E5)/7)+1},parseDate:function(a,b,c){if(a==null||b==null)throw"Invalid arguments";b=typeof b=="object"?b.toString():b+"";if(b== -"")return null;var e=(c?c.shortYearCutoff:null)||this._defaults.shortYearCutoff;e=typeof e!="string"?e:(new Date).getFullYear()%100+parseInt(e,10);for(var f=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,h=(c?c.dayNames:null)||this._defaults.dayNames,i=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort,g=(c?c.monthNames:null)||this._defaults.monthNames,j=c=-1,l=-1,u=-1,k=false,o=function(p){(p=A+1<a.length&&a.charAt(A+1)==p)&&A++;return p},m=function(p){var D=o(p);p=new RegExp("^\\d{1,"+ -(p=="@"?14:p=="!"?20:p=="y"&&D?4:p=="o"?3:2)+"}");p=b.substring(q).match(p);if(!p)throw"Missing number at position "+q;q+=p[0].length;return parseInt(p[0],10)},n=function(p,D,K){p=d.map(o(p)?K:D,function(w,x){return[[x,w]]}).sort(function(w,x){return-(w[1].length-x[1].length)});var E=-1;d.each(p,function(w,x){w=x[1];if(b.substr(q,w.length).toLowerCase()==w.toLowerCase()){E=x[0];q+=w.length;return false}});if(E!=-1)return E+1;else throw"Unknown name at position "+q;},s=function(){if(b.charAt(q)!=a.charAt(A))throw"Unexpected literal at position "+ -q;q++},q=0,A=0;A<a.length;A++)if(k)if(a.charAt(A)=="'"&&!o("'"))k=false;else s();else switch(a.charAt(A)){case "d":l=m("d");break;case "D":n("D",f,h);break;case "o":u=m("o");break;case "m":j=m("m");break;case "M":j=n("M",i,g);break;case "y":c=m("y");break;case "@":var v=new Date(m("@"));c=v.getFullYear();j=v.getMonth()+1;l=v.getDate();break;case "!":v=new Date((m("!")-this._ticksTo1970)/1E4);c=v.getFullYear();j=v.getMonth()+1;l=v.getDate();break;case "'":if(o("'"))s();else k=true;break;default:s()}if(q< -b.length)throw"Extra/unparsed characters found in date: "+b.substring(q);if(c==-1)c=(new Date).getFullYear();else if(c<100)c+=(new Date).getFullYear()-(new Date).getFullYear()%100+(c<=e?0:-100);if(u>-1){j=1;l=u;do{e=this._getDaysInMonth(c,j-1);if(l<=e)break;j++;l-=e}while(1)}v=this._daylightSavingAdjust(new Date(c,j-1,l));if(v.getFullYear()!=c||v.getMonth()+1!=j||v.getDate()!=l)throw"Invalid date";return v},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y", -RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1E7,formatDate:function(a,b,c){if(!b)return"";var e=(c?c.dayNamesShort:null)||this._defaults.dayNamesShort,f=(c?c.dayNames:null)||this._defaults.dayNames,h=(c?c.monthNamesShort:null)||this._defaults.monthNamesShort;c=(c?c.monthNames:null)||this._defaults.monthNames;var i=function(o){(o=k+1<a.length&& -a.charAt(k+1)==o)&&k++;return o},g=function(o,m,n){m=""+m;if(i(o))for(;m.length<n;)m="0"+m;return m},j=function(o,m,n,s){return i(o)?s[m]:n[m]},l="",u=false;if(b)for(var k=0;k<a.length;k++)if(u)if(a.charAt(k)=="'"&&!i("'"))u=false;else l+=a.charAt(k);else switch(a.charAt(k)){case "d":l+=g("d",b.getDate(),2);break;case "D":l+=j("D",b.getDay(),e,f);break;case "o":l+=g("o",Math.round(((new Date(b.getFullYear(),b.getMonth(),b.getDate())).getTime()-(new Date(b.getFullYear(),0,0)).getTime())/864E5),3); -break;case "m":l+=g("m",b.getMonth()+1,2);break;case "M":l+=j("M",b.getMonth(),h,c);break;case "y":l+=i("y")?b.getFullYear():(b.getYear()%100<10?"0":"")+b.getYear()%100;break;case "@":l+=b.getTime();break;case "!":l+=b.getTime()*1E4+this._ticksTo1970;break;case "'":if(i("'"))l+="'";else u=true;break;default:l+=a.charAt(k)}return l},_possibleChars:function(a){for(var b="",c=false,e=function(h){(h=f+1<a.length&&a.charAt(f+1)==h)&&f++;return h},f=0;f<a.length;f++)if(c)if(a.charAt(f)=="'"&&!e("'"))c= -false;else b+=a.charAt(f);else switch(a.charAt(f)){case "d":case "m":case "y":case "@":b+="0123456789";break;case "D":case "M":return null;case "'":if(e("'"))b+="'";else c=true;break;default:b+=a.charAt(f)}return b},_get:function(a,b){return a.settings[b]!==C?a.settings[b]:this._defaults[b]},_setDateFromField:function(a,b){if(a.input.val()!=a.lastVal){var c=this._get(a,"dateFormat"),e=a.lastVal=a.input?a.input.val():null,f,h;f=h=this._getDefaultDate(a);var i=this._getFormatConfig(a);try{f=this.parseDate(c, -e,i)||h}catch(g){this.log(g);e=b?"":e}a.selectedDay=f.getDate();a.drawMonth=a.selectedMonth=f.getMonth();a.drawYear=a.selectedYear=f.getFullYear();a.currentDay=e?f.getDate():0;a.currentMonth=e?f.getMonth():0;a.currentYear=e?f.getFullYear():0;this._adjustInstDate(a)}},_getDefaultDate:function(a){return this._restrictMinMax(a,this._determineDate(a,this._get(a,"defaultDate"),new Date))},_determineDate:function(a,b,c){var e=function(h){var i=new Date;i.setDate(i.getDate()+h);return i},f=function(h){try{return d.datepicker.parseDate(d.datepicker._get(a, -"dateFormat"),h,d.datepicker._getFormatConfig(a))}catch(i){}var g=(h.toLowerCase().match(/^c/)?d.datepicker._getDate(a):null)||new Date,j=g.getFullYear(),l=g.getMonth();g=g.getDate();for(var u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,k=u.exec(h);k;){switch(k[2]||"d"){case "d":case "D":g+=parseInt(k[1],10);break;case "w":case "W":g+=parseInt(k[1],10)*7;break;case "m":case "M":l+=parseInt(k[1],10);g=Math.min(g,d.datepicker._getDaysInMonth(j,l));break;case "y":case "Y":j+=parseInt(k[1],10);g=Math.min(g, -d.datepicker._getDaysInMonth(j,l));break}k=u.exec(h)}return new Date(j,l,g)};if(b=(b=b==null||b===""?c:typeof b=="string"?f(b):typeof b=="number"?isNaN(b)?c:e(b):new Date(b.getTime()))&&b.toString()=="Invalid Date"?c:b){b.setHours(0);b.setMinutes(0);b.setSeconds(0);b.setMilliseconds(0)}return this._daylightSavingAdjust(b)},_daylightSavingAdjust:function(a){if(!a)return null;a.setHours(a.getHours()>12?a.getHours()+2:0);return a},_setDate:function(a,b,c){var e=!b,f=a.selectedMonth,h=a.selectedYear; -b=this._restrictMinMax(a,this._determineDate(a,b,new Date));a.selectedDay=a.currentDay=b.getDate();a.drawMonth=a.selectedMonth=a.currentMonth=b.getMonth();a.drawYear=a.selectedYear=a.currentYear=b.getFullYear();if((f!=a.selectedMonth||h!=a.selectedYear)&&!c)this._notifyChange(a);this._adjustInstDate(a);if(a.input)a.input.val(e?"":this._formatDate(a));if(c=this._get(a,"onSelect")){e=this._formatDate(a);c.apply(a.input?a.input[0]:null,[e,a])}},_getDate:function(a){return!a.currentYear||a.input&&a.input.val()== -""?null:this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay))},_generateHTML:function(a){var b=new Date;b=this._daylightSavingAdjust(new Date(b.getFullYear(),b.getMonth(),b.getDate()));var c=this._get(a,"isRTL"),e=this._get(a,"showButtonPanel"),f=this._get(a,"hideIfNoPrevNext"),h=this._get(a,"navigationAsDateFormat"),i=this._getNumberOfMonths(a),g=this._get(a,"showCurrentAtPos"),j=this._get(a,"stepMonths"),l=i[0]!=1||i[1]!=1,u=this._daylightSavingAdjust(!a.currentDay?new Date(9999, -9,9):new Date(a.currentYear,a.currentMonth,a.currentDay)),k=this._getMinMaxDate(a,"min"),o=this._getMinMaxDate(a,"max");g=a.drawMonth-g;var m=a.drawYear;if(g<0){g+=12;m--}if(o){var n=this._daylightSavingAdjust(new Date(o.getFullYear(),o.getMonth()-i[0]*i[1]+1,o.getDate()));for(n=k&&n<k?k:n;this._daylightSavingAdjust(new Date(m,g,1))>n;){g--;if(g<0){g=11;m--}}}a.drawMonth=g;a.drawYear=m;n=this._get(a,"prevText");n=!h?n:this.formatDate(n,this._daylightSavingAdjust(new Date(m,g-j,1)),this._getFormatConfig(a)); -n=this._canAdjustMonth(a,-1,m,g)?'<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_'+B+".datepicker._adjustDate('#"+a.id+"', -"+j+", 'M');\" title=\""+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>":f?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+n+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"e":"w")+'">'+n+"</span></a>";var s=this._get(a,"nextText");s=!h?s:this.formatDate(s,this._daylightSavingAdjust(new Date(m, -g+j,1)),this._getFormatConfig(a));f=this._canAdjustMonth(a,+1,m,g)?'<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_'+B+".datepicker._adjustDate('#"+a.id+"', +"+j+", 'M');\" title=\""+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>":f?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+s+'"><span class="ui-icon ui-icon-circle-triangle-'+(c?"w":"e")+'">'+s+"</span></a>";j=this._get(a,"currentText");s=this._get(a,"gotoCurrent")&& -a.currentDay?u:b;j=!h?j:this.formatDate(j,s,this._getFormatConfig(a));h=!a.inline?'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_'+B+'.datepicker._hideDatepicker();">'+this._get(a,"closeText")+"</button>":"";e=e?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(c?h:"")+(this._isInRange(a,s)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_'+ -B+".datepicker._gotoToday('#"+a.id+"');\">"+j+"</button>":"")+(c?"":h)+"</div>":"";h=parseInt(this._get(a,"firstDay"),10);h=isNaN(h)?0:h;j=this._get(a,"showWeek");s=this._get(a,"dayNames");this._get(a,"dayNamesShort");var q=this._get(a,"dayNamesMin"),A=this._get(a,"monthNames"),v=this._get(a,"monthNamesShort"),p=this._get(a,"beforeShowDay"),D=this._get(a,"showOtherMonths"),K=this._get(a,"selectOtherMonths");this._get(a,"calculateWeek");for(var E=this._getDefaultDate(a),w="",x=0;x<i[0];x++){var O= -"";this.maxRows=4;for(var G=0;G<i[1];G++){var P=this._daylightSavingAdjust(new Date(m,g,a.selectedDay)),t=" ui-corner-all",y="";if(l){y+='<div class="ui-datepicker-group';if(i[1]>1)switch(G){case 0:y+=" ui-datepicker-group-first";t=" ui-corner-"+(c?"right":"left");break;case i[1]-1:y+=" ui-datepicker-group-last";t=" ui-corner-"+(c?"left":"right");break;default:y+=" ui-datepicker-group-middle";t="";break}y+='">'}y+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+t+'">'+(/all|left/.test(t)&& -x==0?c?f:n:"")+(/all|right/.test(t)&&x==0?c?n:f:"")+this._generateMonthYearHeader(a,g,m,k,o,x>0||G>0,A,v)+'</div><table class="ui-datepicker-calendar"><thead><tr>';var z=j?'<th class="ui-datepicker-week-col">'+this._get(a,"weekHeader")+"</th>":"";for(t=0;t<7;t++){var r=(t+h)%7;z+="<th"+((t+h+6)%7>=5?' class="ui-datepicker-week-end"':"")+'><span title="'+s[r]+'">'+q[r]+"</span></th>"}y+=z+"</tr></thead><tbody>";z=this._getDaysInMonth(m,g);if(m==a.selectedYear&&g==a.selectedMonth)a.selectedDay=Math.min(a.selectedDay, -z);t=(this._getFirstDayOfMonth(m,g)-h+7)%7;z=Math.ceil((t+z)/7);this.maxRows=z=l?this.maxRows>z?this.maxRows:z:z;r=this._daylightSavingAdjust(new Date(m,g,1-t));for(var Q=0;Q<z;Q++){y+="<tr>";var R=!j?"":'<td class="ui-datepicker-week-col">'+this._get(a,"calculateWeek")(r)+"</td>";for(t=0;t<7;t++){var I=p?p.apply(a.input?a.input[0]:null,[r]):[true,""],F=r.getMonth()!=g,L=F&&!K||!I[0]||k&&r<k||o&&r>o;R+='<td class="'+((t+h+6)%7>=5?" ui-datepicker-week-end":"")+(F?" ui-datepicker-other-month":"")+(r.getTime()== -P.getTime()&&g==a.selectedMonth&&a._keyEvent||E.getTime()==r.getTime()&&E.getTime()==P.getTime()?" "+this._dayOverClass:"")+(L?" "+this._unselectableClass+" ui-state-disabled":"")+(F&&!D?"":" "+I[1]+(r.getTime()==u.getTime()?" "+this._currentClass:"")+(r.getTime()==b.getTime()?" ui-datepicker-today":""))+'"'+((!F||D)&&I[2]?' title="'+I[2]+'"':"")+(L?"":' onclick="DP_jQuery_'+B+".datepicker._selectDay('#"+a.id+"',"+r.getMonth()+","+r.getFullYear()+', this);return false;"')+">"+(F&&!D?" ":L?'<span class="ui-state-default">'+ -r.getDate()+"</span>":'<a class="ui-state-default'+(r.getTime()==b.getTime()?" ui-state-highlight":"")+(r.getTime()==u.getTime()?" ui-state-active":"")+(F?" ui-priority-secondary":"")+'" href="#">'+r.getDate()+"</a>")+"</td>";r.setDate(r.getDate()+1);r=this._daylightSavingAdjust(r)}y+=R+"</tr>"}g++;if(g>11){g=0;m++}y+="</tbody></table>"+(l?"</div>"+(i[0]>0&&G==i[1]-1?'<div class="ui-datepicker-row-break"></div>':""):"");O+=y}w+=O}w+=e+(d.browser.msie&&parseInt(d.browser.version,10)<7&&!a.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>': -"");a._keyEvent=false;return w},_generateMonthYearHeader:function(a,b,c,e,f,h,i,g){var j=this._get(a,"changeMonth"),l=this._get(a,"changeYear"),u=this._get(a,"showMonthAfterYear"),k='<div class="ui-datepicker-title">',o="";if(h||!j)o+='<span class="ui-datepicker-month">'+i[b]+"</span>";else{i=e&&e.getFullYear()==c;var m=f&&f.getFullYear()==c;o+='<select class="ui-datepicker-month" onchange="DP_jQuery_'+B+".datepicker._selectMonthYear('#"+a.id+"', this, 'M');\" >";for(var n=0;n<12;n++)if((!i||n>=e.getMonth())&& -(!m||n<=f.getMonth()))o+='<option value="'+n+'"'+(n==b?' selected="selected"':"")+">"+g[n]+"</option>";o+="</select>"}u||(k+=o+(h||!(j&&l)?" ":""));if(!a.yearshtml){a.yearshtml="";if(h||!l)k+='<span class="ui-datepicker-year">'+c+"</span>";else{g=this._get(a,"yearRange").split(":");var s=(new Date).getFullYear();i=function(q){q=q.match(/c[+-].*/)?c+parseInt(q.substring(1),10):q.match(/[+-].*/)?s+parseInt(q,10):parseInt(q,10);return isNaN(q)?s:q};b=i(g[0]);g=Math.max(b,i(g[1]||""));b=e?Math.max(b, -e.getFullYear()):b;g=f?Math.min(g,f.getFullYear()):g;for(a.yearshtml+='<select class="ui-datepicker-year" onchange="DP_jQuery_'+B+".datepicker._selectMonthYear('#"+a.id+"', this, 'Y');\" >";b<=g;b++)a.yearshtml+='<option value="'+b+'"'+(b==c?' selected="selected"':"")+">"+b+"</option>";a.yearshtml+="</select>";k+=a.yearshtml;a.yearshtml=null}}k+=this._get(a,"yearSuffix");if(u)k+=(h||!(j&&l)?" ":"")+o;k+="</div>";return k},_adjustInstDate:function(a,b,c){var e=a.drawYear+(c=="Y"?b:0),f=a.drawMonth+ -(c=="M"?b:0);b=Math.min(a.selectedDay,this._getDaysInMonth(e,f))+(c=="D"?b:0);e=this._restrictMinMax(a,this._daylightSavingAdjust(new Date(e,f,b)));a.selectedDay=e.getDate();a.drawMonth=a.selectedMonth=e.getMonth();a.drawYear=a.selectedYear=e.getFullYear();if(c=="M"||c=="Y")this._notifyChange(a)},_restrictMinMax:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");b=c&&b<c?c:b;return b=a&&b>a?a:b},_notifyChange:function(a){var b=this._get(a,"onChangeMonthYear");if(b)b.apply(a.input? -a.input[0]:null,[a.selectedYear,a.selectedMonth+1,a])},_getNumberOfMonths:function(a){a=this._get(a,"numberOfMonths");return a==null?[1,1]:typeof a=="number"?[1,a]:a},_getMinMaxDate:function(a,b){return this._determineDate(a,this._get(a,b+"Date"),null)},_getDaysInMonth:function(a,b){return 32-this._daylightSavingAdjust(new Date(a,b,32)).getDate()},_getFirstDayOfMonth:function(a,b){return(new Date(a,b,1)).getDay()},_canAdjustMonth:function(a,b,c,e){var f=this._getNumberOfMonths(a);c=this._daylightSavingAdjust(new Date(c, -e+(b<0?b:f[0]*f[1]),1));b<0&&c.setDate(this._getDaysInMonth(c.getFullYear(),c.getMonth()));return this._isInRange(a,c)},_isInRange:function(a,b){var c=this._getMinMaxDate(a,"min");a=this._getMinMaxDate(a,"max");return(!c||b.getTime()>=c.getTime())&&(!a||b.getTime()<=a.getTime())},_getFormatConfig:function(a){var b=this._get(a,"shortYearCutoff");b=typeof b!="string"?b:(new Date).getFullYear()%100+parseInt(b,10);return{shortYearCutoff:b,dayNamesShort:this._get(a,"dayNamesShort"),dayNames:this._get(a, -"dayNames"),monthNamesShort:this._get(a,"monthNamesShort"),monthNames:this._get(a,"monthNames")}},_formatDate:function(a,b,c,e){if(!b){a.currentDay=a.selectedDay;a.currentMonth=a.selectedMonth;a.currentYear=a.selectedYear}b=b?typeof b=="object"?b:this._daylightSavingAdjust(new Date(e,c,b)):this._daylightSavingAdjust(new Date(a.currentYear,a.currentMonth,a.currentDay));return this.formatDate(this._get(a,"dateFormat"),b,this._getFormatConfig(a))}});d.fn.datepicker=function(a){if(!this.length)return this; -if(!d.datepicker.initialized){d(document).mousedown(d.datepicker._checkExternalClick).find("body").append(d.datepicker.dpDiv);d.datepicker.initialized=true}var b=Array.prototype.slice.call(arguments,1);if(typeof a=="string"&&(a=="isDisabled"||a=="getDate"||a=="widget"))return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));if(a=="option"&&arguments.length==2&&typeof arguments[1]=="string")return d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this[0]].concat(b));return this.each(function(){typeof a== -"string"?d.datepicker["_"+a+"Datepicker"].apply(d.datepicker,[this].concat(b)):d.datepicker._attachDatepicker(this,a)})};d.datepicker=new M;d.datepicker.initialized=false;d.datepicker.uuid=(new Date).getTime();d.datepicker.version="1.8.15";window["DP_jQuery_"+B]=d})(jQuery); -;/* - * jQuery UI Progressbar 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Progressbar - * - * Depends: - * jquery.ui.core.js - * jquery.ui.widget.js - */ -(function(b,d){b.widget("ui.progressbar",{options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()});this.valueDiv=b("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element);this.oldValue=this._value();this._refreshValue()},destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"); -this.valueDiv.remove();b.Widget.prototype.destroy.apply(this,arguments)},value:function(a){if(a===d)return this._value();this._setOption("value",a);return this},_setOption:function(a,c){if(a==="value"){this.options.value=c;this._refreshValue();this._value()===this.options.max&&this._trigger("complete")}b.Widget.prototype._setOption.apply(this,arguments)},_value:function(){var a=this.options.value;if(typeof a!=="number")a=0;return Math.min(this.options.max,Math.max(this.min,a))},_percentage:function(){return 100* -this._value()/this.options.max},_refreshValue:function(){var a=this.value(),c=this._percentage();if(this.oldValue!==a){this.oldValue=a;this._trigger("change")}this.valueDiv.toggle(a>this.min).toggleClass("ui-corner-right",a===this.options.max).width(c.toFixed(0)+"%");this.element.attr("aria-valuenow",a)}});b.extend(b.ui.progressbar,{version:"1.8.15"})})(jQuery); -;/* - * jQuery UI Effects 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/ - */ -jQuery.effects||function(f,j){function m(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], -16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return n.transparent;return n[f.trim(c).toLowerCase()]}function s(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return m(b)}function o(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, -a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function p(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in t||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function u(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= -a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:b in f.fx.speeds?f.fx.speeds[b]:f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}function l(c){if(!c||typeof c==="number"||f.fx.speeds[c])return true;if(typeof c==="string"&&!f.effects[c])return true;return false}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor", -"borderTopColor","borderColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=s(b.elem,a);b.end=m(b.end);b.colorInit=true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var n={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0, -0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211, -211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},q=["add","remove","toggle"],t={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b, -d){if(f.isFunction(b)){d=b;b=null}return this.queue(function(){var e=f(this),g=e.attr("style")||" ",h=p(o.call(this)),r,v=e.attr("class");f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});r=p(o.call(this));e.attr("class",v);e.animate(u(h,r),{queue:false,duration:a,easing:b,complete:function(){f.each(q,function(w,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments);f.dequeue(this)}})})}; -f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this, -[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.15",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b= -0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent();var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}); -c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"});c.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c, -a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments),b={options:a[1],duration:a[2],callback:a[3]};a=b.options.mode;var d=f.effects[c];if(f.fx.off||!d)return a?this[a](b.duration,b.callback):this.each(function(){b.callback&&b.callback.call(this)});return d.call(this,b)},_show:f.fn.show,show:function(c){if(l(c))return this._show.apply(this,arguments);else{var a=k.apply(this,arguments); -a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(l(c))return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(l(c)||typeof c==="boolean"||f.isFunction(c))return this.__toggle.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%", -"pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d* -((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/= -e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2,10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/= -e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)*a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/ -h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5* -h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c, -e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,d,e)*0.5+b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery); -;/* - * jQuery UI Effects Blind 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Blind - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.blind=function(c){return this.queue(function(){var a=b(this),g=["position","top","bottom","left","right"],f=b.effects.setMode(a,c.options.mode||"hide"),d=c.options.direction||"vertical";b.effects.save(a,g);a.show();var e=b.effects.createWrapper(a).css({overflow:"hidden"}),h=d=="vertical"?"height":"width";d=d=="vertical"?e.height():e.width();f=="show"&&e.css(h,0);var i={};i[h]=f=="show"?d:0;e.animate(i,c.duration,c.options.easing,function(){f=="hide"&&a.hide();b.effects.restore(a, -g);b.effects.removeWrapper(a);c.callback&&c.callback.apply(a[0],arguments);a.dequeue()})})}})(jQuery); -;/* - * jQuery UI Effects Bounce 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Bounce - * - * Depends: - * jquery.effects.core.js - */ -(function(e){e.effects.bounce=function(b){return this.queue(function(){var a=e(this),l=["position","top","bottom","left","right"],h=e.effects.setMode(a,b.options.mode||"effect"),d=b.options.direction||"up",c=b.options.distance||20,m=b.options.times||5,i=b.duration||250;/show|hide/.test(h)&&l.push("opacity");e.effects.save(a,l);a.show();e.effects.createWrapper(a);var f=d=="up"||d=="down"?"top":"left";d=d=="up"||d=="left"?"pos":"neg";c=b.options.distance||(f=="top"?a.outerHeight({margin:true})/3:a.outerWidth({margin:true})/ -3);if(h=="show")a.css("opacity",0).css(f,d=="pos"?-c:c);if(h=="hide")c/=m*2;h!="hide"&&m--;if(h=="show"){var g={opacity:1};g[f]=(d=="pos"?"+=":"-=")+c;a.animate(g,i/2,b.options.easing);c/=2;m--}for(g=0;g<m;g++){var j={},k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing);c=h=="hide"?c*2:c/2}if(h=="hide"){g={opacity:0};g[f]=(d=="pos"?"-=":"+=")+c;a.animate(g,i/2,b.options.easing,function(){a.hide();e.effects.restore(a,l);e.effects.removeWrapper(a); -b.callback&&b.callback.apply(this,arguments)})}else{j={};k={};j[f]=(d=="pos"?"-=":"+=")+c;k[f]=(d=="pos"?"+=":"-=")+c;a.animate(j,i/2,b.options.easing).animate(k,i/2,b.options.easing,function(){e.effects.restore(a,l);e.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments)})}a.queue("fx",function(){a.dequeue()});a.dequeue()})}})(jQuery); -;/* - * jQuery UI Effects Clip 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Clip - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.clip=function(e){return this.queue(function(){var a=b(this),i=["position","top","bottom","left","right","height","width"],f=b.effects.setMode(a,e.options.mode||"hide"),c=e.options.direction||"vertical";b.effects.save(a,i);a.show();var d=b.effects.createWrapper(a).css({overflow:"hidden"});d=a[0].tagName=="IMG"?d:a;var g={size:c=="vertical"?"height":"width",position:c=="vertical"?"top":"left"};c=c=="vertical"?d.height():d.width();if(f=="show"){d.css(g.size,0);d.css(g.position, -c/2)}var h={};h[g.size]=f=="show"?c:0;h[g.position]=f=="show"?0:c/2;d.animate(h,{queue:false,duration:e.duration,easing:e.options.easing,complete:function(){f=="hide"&&a.hide();b.effects.restore(a,i);b.effects.removeWrapper(a);e.callback&&e.callback.apply(a[0],arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Drop 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Drop - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.drop=function(d){return this.queue(function(){var a=c(this),h=["position","top","bottom","left","right","opacity"],e=c.effects.setMode(a,d.options.mode||"hide"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a);var f=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var g=d.options.distance||(f=="top"?a.outerHeight({margin:true})/2:a.outerWidth({margin:true})/2);if(e=="show")a.css("opacity",0).css(f,b=="pos"?-g:g);var i={opacity:e== -"show"?1:0};i[f]=(e=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+g;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){e=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Explode 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Explode - * - * Depends: - * jquery.effects.core.js - */ -(function(j){j.effects.explode=function(a){return this.queue(function(){var c=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3,d=a.options.pieces?Math.round(Math.sqrt(a.options.pieces)):3;a.options.mode=a.options.mode=="toggle"?j(this).is(":visible")?"hide":"show":a.options.mode;var b=j(this).show().css("visibility","hidden"),g=b.offset();g.top-=parseInt(b.css("marginTop"),10)||0;g.left-=parseInt(b.css("marginLeft"),10)||0;for(var h=b.outerWidth(true),i=b.outerHeight(true),e=0;e<c;e++)for(var f= -0;f<d;f++)b.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-f*(h/d),top:-e*(i/c)}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:h/d,height:i/c,left:g.left+f*(h/d)+(a.options.mode=="show"?(f-Math.floor(d/2))*(h/d):0),top:g.top+e*(i/c)+(a.options.mode=="show"?(e-Math.floor(c/2))*(i/c):0),opacity:a.options.mode=="show"?0:1}).animate({left:g.left+f*(h/d)+(a.options.mode=="show"?0:(f-Math.floor(d/2))*(h/d)),top:g.top+ -e*(i/c)+(a.options.mode=="show"?0:(e-Math.floor(c/2))*(i/c)),opacity:a.options.mode=="show"?1:0},a.duration||500);setTimeout(function(){a.options.mode=="show"?b.css({visibility:"visible"}):b.css({visibility:"visible"}).hide();a.callback&&a.callback.apply(b[0]);b.dequeue();j("div.ui-effects-explode").remove()},a.duration||500)})}})(jQuery); -;/* - * jQuery UI Effects Fade 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fade - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.fade=function(a){return this.queue(function(){var c=b(this),d=b.effects.setMode(c,a.options.mode||"hide");c.animate({opacity:d},{queue:false,duration:a.duration,easing:a.options.easing,complete:function(){a.callback&&a.callback.apply(this,arguments);c.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Fold 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Fold - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.fold=function(a){return this.queue(function(){var b=c(this),j=["position","top","bottom","left","right"],d=c.effects.setMode(b,a.options.mode||"hide"),g=a.options.size||15,h=!!a.options.horizFirst,k=a.duration?a.duration/2:c.fx.speeds._default/2;c.effects.save(b,j);b.show();var e=c.effects.createWrapper(b).css({overflow:"hidden"}),f=d=="show"!=h,l=f?["width","height"]:["height","width"];f=f?[e.width(),e.height()]:[e.height(),e.width()];var i=/([0-9]+)%/.exec(g);if(i)g=parseInt(i[1], -10)/100*f[d=="hide"?0:1];if(d=="show")e.css(h?{height:0,width:g}:{height:g,width:0});h={};i={};h[l[0]]=d=="show"?f[0]:g;i[l[1]]=d=="show"?f[1]:0;e.animate(h,k,a.options.easing).animate(i,k,a.options.easing,function(){d=="hide"&&b.hide();c.effects.restore(b,j);c.effects.removeWrapper(b);a.callback&&a.callback.apply(b[0],arguments);b.dequeue()})})}})(jQuery); -;/* - * jQuery UI Effects Highlight 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Highlight - * - * Depends: - * jquery.effects.core.js - */ -(function(b){b.effects.highlight=function(c){return this.queue(function(){var a=b(this),e=["backgroundImage","backgroundColor","opacity"],d=b.effects.setMode(a,c.options.mode||"show"),f={backgroundColor:a.css("backgroundColor")};if(d=="hide")f.opacity=0;b.effects.save(a,e);a.show().css({backgroundImage:"none",backgroundColor:c.options.color||"#ffff99"}).animate(f,{queue:false,duration:c.duration,easing:c.options.easing,complete:function(){d=="hide"&&a.hide();b.effects.restore(a,e);d=="show"&&!b.support.opacity&& -this.style.removeAttribute("filter");c.callback&&c.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Pulsate 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Pulsate - * - * Depends: - * jquery.effects.core.js - */ -(function(d){d.effects.pulsate=function(a){return this.queue(function(){var b=d(this),c=d.effects.setMode(b,a.options.mode||"show");times=(a.options.times||5)*2-1;duration=a.duration?a.duration/2:d.fx.speeds._default/2;isVisible=b.is(":visible");animateTo=0;if(!isVisible){b.css("opacity",0).show();animateTo=1}if(c=="hide"&&isVisible||c=="show"&&!isVisible)times--;for(c=0;c<times;c++){b.animate({opacity:animateTo},duration,a.options.easing);animateTo=(animateTo+1)%2}b.animate({opacity:animateTo},duration, -a.options.easing,function(){animateTo==0&&b.hide();a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()}).dequeue()})}})(jQuery); -;/* - * jQuery UI Effects Scale 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Scale - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.puff=function(b){return this.queue(function(){var a=c(this),e=c.effects.setMode(a,b.options.mode||"hide"),g=parseInt(b.options.percent,10)||150,h=g/100,i={height:a.height(),width:a.width()};c.extend(b.options,{fade:true,mode:e,percent:e=="hide"?g:100,from:e=="hide"?i:{height:i.height*h,width:i.width*h}});a.effect("scale",b.options,b.duration,b.callback);a.dequeue()})};c.effects.scale=function(b){return this.queue(function(){var a=c(this),e=c.extend(true,{},b.options),g=c.effects.setMode(a, -b.options.mode||"effect"),h=parseInt(b.options.percent,10)||(parseInt(b.options.percent,10)==0?0:g=="hide"?0:100),i=b.options.direction||"both",f=b.options.origin;if(g!="effect"){e.origin=f||["middle","center"];e.restore=true}f={height:a.height(),width:a.width()};a.from=b.options.from||(g=="show"?{height:0,width:0}:f);h={y:i!="horizontal"?h/100:1,x:i!="vertical"?h/100:1};a.to={height:f.height*h.y,width:f.width*h.x};if(b.options.fade){if(g=="show"){a.from.opacity=0;a.to.opacity=1}if(g=="hide"){a.from.opacity= -1;a.to.opacity=0}}e.from=a.from;e.to=a.to;e.mode=g;a.effect("size",e,b.duration,b.callback);a.dequeue()})};c.effects.size=function(b){return this.queue(function(){var a=c(this),e=["position","top","bottom","left","right","width","height","overflow","opacity"],g=["position","top","bottom","left","right","overflow","opacity"],h=["width","height","overflow"],i=["fontSize"],f=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],k=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"], -p=c.effects.setMode(a,b.options.mode||"effect"),n=b.options.restore||false,m=b.options.scale||"both",l=b.options.origin,j={height:a.height(),width:a.width()};a.from=b.options.from||j;a.to=b.options.to||j;if(l){l=c.effects.getBaseline(l,j);a.from.top=(j.height-a.from.height)*l.y;a.from.left=(j.width-a.from.width)*l.x;a.to.top=(j.height-a.to.height)*l.y;a.to.left=(j.width-a.to.width)*l.x}var d={from:{y:a.from.height/j.height,x:a.from.width/j.width},to:{y:a.to.height/j.height,x:a.to.width/j.width}}; -if(m=="box"||m=="both"){if(d.from.y!=d.to.y){e=e.concat(f);a.from=c.effects.setTransition(a,f,d.from.y,a.from);a.to=c.effects.setTransition(a,f,d.to.y,a.to)}if(d.from.x!=d.to.x){e=e.concat(k);a.from=c.effects.setTransition(a,k,d.from.x,a.from);a.to=c.effects.setTransition(a,k,d.to.x,a.to)}}if(m=="content"||m=="both")if(d.from.y!=d.to.y){e=e.concat(i);a.from=c.effects.setTransition(a,i,d.from.y,a.from);a.to=c.effects.setTransition(a,i,d.to.y,a.to)}c.effects.save(a,n?e:g);a.show();c.effects.createWrapper(a); -a.css("overflow","hidden").css(a.from);if(m=="content"||m=="both"){f=f.concat(["marginTop","marginBottom"]).concat(i);k=k.concat(["marginLeft","marginRight"]);h=e.concat(f).concat(k);a.find("*[width]").each(function(){child=c(this);n&&c.effects.save(child,h);var o={height:child.height(),width:child.width()};child.from={height:o.height*d.from.y,width:o.width*d.from.x};child.to={height:o.height*d.to.y,width:o.width*d.to.x};if(d.from.y!=d.to.y){child.from=c.effects.setTransition(child,f,d.from.y,child.from); -child.to=c.effects.setTransition(child,f,d.to.y,child.to)}if(d.from.x!=d.to.x){child.from=c.effects.setTransition(child,k,d.from.x,child.from);child.to=c.effects.setTransition(child,k,d.to.x,child.to)}child.css(child.from);child.animate(child.to,b.duration,b.options.easing,function(){n&&c.effects.restore(child,h)})})}a.animate(a.to,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){a.to.opacity===0&&a.css("opacity",a.from.opacity);p=="hide"&&a.hide();c.effects.restore(a, -n?e:g);c.effects.removeWrapper(a);b.callback&&b.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Shake 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Shake - * - * Depends: - * jquery.effects.core.js - */ -(function(d){d.effects.shake=function(a){return this.queue(function(){var b=d(this),j=["position","top","bottom","left","right"];d.effects.setMode(b,a.options.mode||"effect");var c=a.options.direction||"left",e=a.options.distance||20,l=a.options.times||3,f=a.duration||a.options.duration||140;d.effects.save(b,j);b.show();d.effects.createWrapper(b);var g=c=="up"||c=="down"?"top":"left",h=c=="up"||c=="left"?"pos":"neg";c={};var i={},k={};c[g]=(h=="pos"?"-=":"+=")+e;i[g]=(h=="pos"?"+=":"-=")+e*2;k[g]= -(h=="pos"?"-=":"+=")+e*2;b.animate(c,f,a.options.easing);for(e=1;e<l;e++)b.animate(i,f,a.options.easing).animate(k,f,a.options.easing);b.animate(i,f,a.options.easing).animate(c,f/2,a.options.easing,function(){d.effects.restore(b,j);d.effects.removeWrapper(b);a.callback&&a.callback.apply(this,arguments)});b.queue("fx",function(){b.dequeue()});b.dequeue()})}})(jQuery); -;/* - * jQuery UI Effects Slide 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Slide - * - * Depends: - * jquery.effects.core.js - */ -(function(c){c.effects.slide=function(d){return this.queue(function(){var a=c(this),h=["position","top","bottom","left","right"],f=c.effects.setMode(a,d.options.mode||"show"),b=d.options.direction||"left";c.effects.save(a,h);a.show();c.effects.createWrapper(a).css({overflow:"hidden"});var g=b=="up"||b=="down"?"top":"left";b=b=="up"||b=="left"?"pos":"neg";var e=d.options.distance||(g=="top"?a.outerHeight({margin:true}):a.outerWidth({margin:true}));if(f=="show")a.css(g,b=="pos"?isNaN(e)?"-"+e:-e:e); -var i={};i[g]=(f=="show"?b=="pos"?"+=":"-=":b=="pos"?"-=":"+=")+e;a.animate(i,{queue:false,duration:d.duration,easing:d.options.easing,complete:function(){f=="hide"&&a.hide();c.effects.restore(a,h);c.effects.removeWrapper(a);d.callback&&d.callback.apply(this,arguments);a.dequeue()}})})}})(jQuery); -;/* - * jQuery UI Effects Transfer 1.8.15 - * - * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * http://docs.jquery.com/UI/Effects/Transfer - * - * Depends: - * jquery.effects.core.js - */ -(function(e){e.effects.transfer=function(a){return this.queue(function(){var b=e(this),c=e(a.options.to),d=c.offset();c={top:d.top,left:d.left,height:c.innerHeight(),width:c.innerWidth()};d=b.offset();var f=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(a.options.className).css({top:d.top,left:d.left,height:b.innerHeight(),width:b.innerWidth(),position:"absolute"}).animate(c,a.duration,a.options.easing,function(){f.remove();a.callback&&a.callback.apply(b[0],arguments); -b.dequeue()})})}})(jQuery); -; diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui.LICENSE deleted file mode 100644 index e1f050a705d745eec851f123881f3300334741d1..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/jquery-ui.LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -jQuery UI is used under the terms of the MIT License -http://jquery.org/license/ - ---- - -Copyright 2012 jQuery Foundation and other contributors -http://jquery.com/ - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr-1.7.min.js b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr-1.7.min.js deleted file mode 100644 index 5a068716a2596e2963aa9b08c0b4e53fa5ef9620..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr-1.7.min.js +++ /dev/null @@ -1,2 +0,0 @@ -// Modernizr v1.7 www.modernizr.com -window.Modernizr=function(a,b,c){function G(){e.input=function(a){for(var b=0,c=a.length;b<c;b++)t[a[b]]=!!(a[b]in l);return t}("autocomplete autofocus list placeholder max min multiple pattern required step".split(" ")),e.inputtypes=function(a){for(var d=0,e,f,h,i=a.length;d<i;d++)l.setAttribute("type",f=a[d]),e=l.type!=="text",e&&(l.value=m,l.style.cssText="position:absolute;visibility:hidden;",/^range$/.test(f)&&l.style.WebkitAppearance!==c?(g.appendChild(l),h=b.defaultView,e=h.getComputedStyle&&h.getComputedStyle(l,null).WebkitAppearance!=="textfield"&&l.offsetHeight!==0,g.removeChild(l)):/^(search|tel)$/.test(f)||(/^(url|email)$/.test(f)?e=l.checkValidity&&l.checkValidity()===!1:/^color$/.test(f)?(g.appendChild(l),g.offsetWidth,e=l.value!=m,g.removeChild(l)):e=l.value!=m)),s[a[d]]=!!e;return s}("search tel url email datetime date month week time datetime-local number range color".split(" "))}function F(a,b){var c=a.charAt(0).toUpperCase()+a.substr(1),d=(a+" "+p.join(c+" ")+c).split(" ");return!!E(d,b)}function E(a,b){for(var d in a)if(k[a[d]]!==c&&(!b||b(a[d],j)))return!0}function D(a,b){return(""+a).indexOf(b)!==-1}function C(a,b){return typeof a===b}function B(a,b){return A(o.join(a+";")+(b||""))}function A(a){k.cssText=a}var d="1.7",e={},f=!0,g=b.documentElement,h=b.head||b.getElementsByTagName("head")[0],i="modernizr",j=b.createElement(i),k=j.style,l=b.createElement("input"),m=":)",n=Object.prototype.toString,o=" -webkit- -moz- -o- -ms- -khtml- ".split(" "),p="Webkit Moz O ms Khtml".split(" "),q={svg:"http://www.w3.org/2000/svg"},r={},s={},t={},u=[],v,w=function(a){var c=b.createElement("style"),d=b.createElement("div"),e;c.textContent=a+"{#modernizr{height:3px}}",h.appendChild(c),d.id="modernizr",g.appendChild(d),e=d.offsetHeight===3,c.parentNode.removeChild(c),d.parentNode.removeChild(d);return!!e},x=function(){function d(d,e){e=e||b.createElement(a[d]||"div");var f=(d="on"+d)in e;f||(e.setAttribute||(e=b.createElement("div")),e.setAttribute&&e.removeAttribute&&(e.setAttribute(d,""),f=C(e[d],"function"),C(e[d],c)||(e[d]=c),e.removeAttribute(d))),e=null;return f}var a={select:"input",change:"input",submit:"form",reset:"form",error:"img",load:"img",abort:"img"};return d}(),y=({}).hasOwnProperty,z;C(y,c)||C(y.call,c)?z=function(a,b){return b in a&&C(a.constructor.prototype[b],c)}:z=function(a,b){return y.call(a,b)},r.flexbox=function(){function c(a,b,c,d){a.style.cssText=o.join(b+":"+c+";")+(d||"")}function a(a,b,c,d){b+=":",a.style.cssText=(b+o.join(c+";"+b)).slice(0,-b.length)+(d||"")}var d=b.createElement("div"),e=b.createElement("div");a(d,"display","box","width:42px;padding:0;"),c(e,"box-flex","1","width:10px;"),d.appendChild(e),g.appendChild(d);var f=e.offsetWidth===42;d.removeChild(e),g.removeChild(d);return f},r.canvas=function(){var a=b.createElement("canvas");return a.getContext&&a.getContext("2d")},r.canvastext=function(){return e.canvas&&C(b.createElement("canvas").getContext("2d").fillText,"function")},r.webgl=function(){return!!a.WebGLRenderingContext},r.touch=function(){return"ontouchstart"in a||w("@media ("+o.join("touch-enabled),(")+"modernizr)")},r.geolocation=function(){return!!navigator.geolocation},r.postmessage=function(){return!!a.postMessage},r.websqldatabase=function(){var b=!!a.openDatabase;return b},r.indexedDB=function(){for(var b=-1,c=p.length;++b<c;){var d=p[b].toLowerCase();if(a[d+"_indexedDB"]||a[d+"IndexedDB"])return!0}return!1},r.hashchange=function(){return x("hashchange",a)&&(b.documentMode===c||b.documentMode>7)},r.history=function(){return !!(a.history&&history.pushState)},r.draganddrop=function(){return x("dragstart")&&x("drop")},r.websockets=function(){return"WebSocket"in a},r.rgba=function(){A("background-color:rgba(150,255,150,.5)");return D(k.backgroundColor,"rgba")},r.hsla=function(){A("background-color:hsla(120,40%,100%,.5)");return D(k.backgroundColor,"rgba")||D(k.backgroundColor,"hsla")},r.multiplebgs=function(){A("background:url(//:),url(//:),red url(//:)");return(new RegExp("(url\\s*\\(.*?){3}")).test(k.background)},r.backgroundsize=function(){return F("backgroundSize")},r.borderimage=function(){return F("borderImage")},r.borderradius=function(){return F("borderRadius","",function(a){return D(a,"orderRadius")})},r.boxshadow=function(){return F("boxShadow")},r.textshadow=function(){return b.createElement("div").style.textShadow===""},r.opacity=function(){B("opacity:.55");return/^0.55$/.test(k.opacity)},r.cssanimations=function(){return F("animationName")},r.csscolumns=function(){return F("columnCount")},r.cssgradients=function(){var a="background-image:",b="gradient(linear,left top,right bottom,from(#9f9),to(white));",c="linear-gradient(left top,#9f9, white);";A((a+o.join(b+a)+o.join(c+a)).slice(0,-a.length));return D(k.backgroundImage,"gradient")},r.cssreflections=function(){return F("boxReflect")},r.csstransforms=function(){return!!E(["transformProperty","WebkitTransform","MozTransform","OTransform","msTransform"])},r.csstransforms3d=function(){var a=!!E(["perspectiveProperty","WebkitPerspective","MozPerspective","OPerspective","msPerspective"]);a&&"webkitPerspective"in g.style&&(a=w("@media ("+o.join("transform-3d),(")+"modernizr)"));return a},r.csstransitions=function(){return F("transitionProperty")},r.fontface=function(){var a,c,d=h||g,e=b.createElement("style"),f=b.implementation||{hasFeature:function(){return!1}};e.type="text/css",d.insertBefore(e,d.firstChild),a=e.sheet||e.styleSheet;var i=f.hasFeature("CSS2","")?function(b){if(!a||!b)return!1;var c=!1;try{a.insertRule(b,0),c=/src/i.test(a.cssRules[0].cssText),a.deleteRule(a.cssRules.length-1)}catch(d){}return c}:function(b){if(!a||!b)return!1;a.cssText=b;return a.cssText.length!==0&&/src/i.test(a.cssText)&&a.cssText.replace(/\r+|\n+/g,"").indexOf(b.split(" ")[0])===0};c=i('@font-face { font-family: "font"; src: url(data:,); }'),d.removeChild(e);return c},r.video=function(){var a=b.createElement("video"),c=!!a.canPlayType;if(c){c=new Boolean(c),c.ogg=a.canPlayType('video/ogg; codecs="theora"');var d='video/mp4; codecs="avc1.42E01E';c.h264=a.canPlayType(d+'"')||a.canPlayType(d+', mp4a.40.2"'),c.webm=a.canPlayType('video/webm; codecs="vp8, vorbis"')}return c},r.audio=function(){var a=b.createElement("audio"),c=!!a.canPlayType;c&&(c=new Boolean(c),c.ogg=a.canPlayType('audio/ogg; codecs="vorbis"'),c.mp3=a.canPlayType("audio/mpeg;"),c.wav=a.canPlayType('audio/wav; codecs="1"'),c.m4a=a.canPlayType("audio/x-m4a;")||a.canPlayType("audio/aac;"));return c},r.localstorage=function(){try{return!!localStorage.getItem}catch(a){return!1}},r.sessionstorage=function(){try{return!!sessionStorage.getItem}catch(a){return!1}},r.webWorkers=function(){return!!a.Worker},r.applicationcache=function(){return!!a.applicationCache},r.svg=function(){return!!b.createElementNS&&!!b.createElementNS(q.svg,"svg").createSVGRect},r.inlinesvg=function(){var a=b.createElement("div");a.innerHTML="<svg/>";return(a.firstChild&&a.firstChild.namespaceURI)==q.svg},r.smil=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"animate")))},r.svgclippaths=function(){return!!b.createElementNS&&/SVG/.test(n.call(b.createElementNS(q.svg,"clipPath")))};for(var H in r)z(r,H)&&(v=H.toLowerCase(),e[v]=r[H](),u.push((e[v]?"":"no-")+v));e.input||G(),e.crosswindowmessaging=e.postmessage,e.historymanagement=e.history,e.addTest=function(a,b){a=a.toLowerCase();if(!e[a]){b=!!b(),g.className+=" "+(b?"":"no-")+a,e[a]=b;return e}},A(""),j=l=null,f&&a.attachEvent&&function(){var a=b.createElement("div");a.innerHTML="<elem></elem>";return a.childNodes.length!==1}()&&function(a,b){function p(a,b){var c=-1,d=a.length,e,f=[];while(++c<d)e=a[c],(b=e.media||b)!="screen"&&f.push(p(e.imports,b),e.cssText);return f.join("")}function o(a){var b=-1;while(++b<e)a.createElement(d[b])}var c="abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",d=c.split("|"),e=d.length,f=new RegExp("(^|\\s)("+c+")","gi"),g=new RegExp("<(/*)("+c+")","gi"),h=new RegExp("(^|[^\\n]*?\\s)("+c+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),i=b.createDocumentFragment(),j=b.documentElement,k=j.firstChild,l=b.createElement("body"),m=b.createElement("style"),n;o(b),o(i),k.insertBefore(m,k.firstChild),m.media="print",a.attachEvent("onbeforeprint",function(){var a=-1,c=p(b.styleSheets,"all"),k=[],o;n=n||b.body;while((o=h.exec(c))!=null)k.push((o[1]+o[2]+o[3]).replace(f,"$1.iepp_$2")+o[4]);m.styleSheet.cssText=k.join("\n");while(++a<e){var q=b.getElementsByTagName(d[a]),r=q.length,s=-1;while(++s<r)q[s].className.indexOf("iepp_")<0&&(q[s].className+=" iepp_"+d[a])}i.appendChild(n),j.appendChild(l),l.className=n.className,l.innerHTML=n.innerHTML.replace(g,"<$1font")}),a.attachEvent("onafterprint",function(){l.innerHTML="",j.removeChild(l),j.appendChild(n),m.styleSheet.cssText=""})}(a,b),e._enableHTML5=f,e._version=d,g.className=g.className.replace(/\bno-js\b/,"")+" js "+u.join(" ");return e}(this,this.document) diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr.LICENSE deleted file mode 100644 index 4de3c2e4df4e1e96dc8de82cdcb5e13bdf91b010..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/js/modernizr.LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Modernizer is used under the terms of the MIT License -http://modernizr.com/license/ - ---- - -Copyright (c) Faruk Ates, Paul Irish, Alex Sexton - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/HTML5Boilerplate.LICENSE b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/HTML5Boilerplate.LICENSE deleted file mode 100644 index 00d2e135a7ee7b81c27fed80ddf6ee341c8d6752..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/HTML5Boilerplate.LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to <http://unlicense.org/> \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/administrative/administrative.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/administrative/administrative.xsl deleted file mode 100644 index 2e627a834d71e159a0ec11cf7273ac7fe229e467..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/administrative/administrative.xsl +++ /dev/null @@ -1,131 +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/ - ---> -<!-- - Modifications to the rendering of elements in the administrative aspect. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!--Add the class 'tabbed' to the form for administrative pages containing tabs and wrap the tab content with a div with class 'pane', - the rest is just a copy of the default interactive div template--> - <xsl:template match="dri:div[contains(@rend, 'administrative') and dri:list[@rend = 'horizontal']]"> - <xsl:apply-templates select="dri:head"/> - <xsl:apply-templates select="@pagination"> - <xsl:with-param name="position">top</xsl:with-param> - </xsl:apply-templates> - <form> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class">ds-interactive-div tabbed</xsl:with-param> - </xsl:call-template> - <xsl:attribute name="action"><xsl:value-of select="@action"/></xsl:attribute> - <xsl:attribute name="method"><xsl:value-of select="@method"/></xsl:attribute> - <xsl:if test="@method='multipart'"> - <xsl:attribute name="method">post</xsl:attribute> - <xsl:attribute name="enctype">multipart/form-data</xsl:attribute> - </xsl:if> - <xsl:attribute name="onsubmit">javascript:tSubmit(this);</xsl:attribute> - <!--For Item Submission process, disable ability to submit a form by pressing 'Enter'--> - <xsl:if test="starts-with(@n,'submit')"> - <xsl:attribute name="onkeydown">javascript:return disableEnterKey(event);</xsl:attribute> - </xsl:if> - <xsl:apply-templates select="dri:list[@rend = 'horizontal']"/> - <div class="pane"> - <xsl:apply-templates select="*[not(name()='head' or @rend = 'horizontal')]"/> - </div> - - </form> - <!-- JS to scroll form to DIV parent of "Add" button if jump-to --> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='jumpTo']"> - <script type="text/javascript"> - <xsl:text>var button = document.getElementById('</xsl:text> - <xsl:value-of select="translate(@id,'.','_')"/> - <xsl:text>').elements['</xsl:text> - <xsl:value-of select="concat('submit_',/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='jumpTo'],'_add')"/> - <xsl:text>'];</xsl:text> - <xsl:text> - if (button != null) { - var n = button.parentNode; - for (; n != null; n = n.parentNode) { - if (n.tagName == 'DIV') { - n.scrollIntoView(false); - break; - } - } - } - </xsl:text> - </script> - </xsl:if> - <xsl:apply-templates select="@pagination"> - <xsl:with-param name="position">bottom</xsl:with-param> - </xsl:apply-templates> - </xsl:template> - - - <!--the tabs are floating, so give the ul the class 'clearfix' to ensure it has a height--> - <xsl:template match="dri:div[contains(@rend, 'administrative')]/dri:list[@rend = 'horizontal']"> - <xsl:apply-templates select="dri:head"/> - <ul> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class">ds-simple-list clearfix</xsl:with-param> - </xsl:call-template> - <xsl:apply-templates select="*[not(name()='head')]" mode="nested"/> - </ul> - </xsl:template> - - <!--give the active tab the class 'active-tab'--> - <xsl:template match="dri:div[contains(@rend, 'administrative')]/dri:list[@rend = 'horizontal']/dri:item[dri:hi[@rend = 'bold']]" mode="nested"> - <li class="active-tab"> - <xsl:apply-templates /> - </li> - </xsl:template> - - <!--Template for the bitstream reordering--> - <xsl:template match="dri:cell[starts-with(@id, 'aspect.administrative.item.EditItemBitstreamsForm.cell.bitstream_order_')]" priority="2"> - <td> - <xsl:call-template name="standardAttributes"/> - <xsl:apply-templates select="*[not(@type='button')]" /> - <!--A div that will indicate the old & the new order--> - <div> - <span> - <!--Give this one an ID so that the javascript can change his value--> - <xsl:attribute name="id"> - <xsl:value-of select="dri:field/@id"/> - <xsl:text>_new</xsl:text> - </xsl:attribute> - <xsl:value-of select="dri:field/dri:value"/> - </span> - <xsl:text> (</xsl:text> - <i18n:text>xmlui.administrative.item.EditItemBitstreamsForm.previous_order</i18n:text> - <xsl:value-of select="dri:field/dri:value"/> - <xsl:text>)</xsl:text> - </div> - </td> - <td> - <xsl:apply-templates select="dri:field[@type='button']"/> - </td> - </xsl:template> - -</xsl:stylesheet> \ No newline at end of file diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/collection-list.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/collection-list.xsl deleted file mode 100644 index 560b6d5a270e908771079adbe44cd7db28c97888..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/collection-list.xsl +++ /dev/null @@ -1,106 +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/ - ---> -<!-- - Rendering of a list of collections (e.g. on a community homepage, - or on the community-list page) - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet - xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:atom="http://www.w3.org/2005/Atom" - xmlns:ore="http://www.openarchives.org/ore/terms/" - xmlns:oreatom="http://www.openarchives.org/ore/atom/" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:xalan="http://xml.apache.org/xalan" - xmlns:encoder="xalan://java.net.URLEncoder" - xmlns:util="org.dspace.app.xmlui.utils.XSLUtils" - xmlns:confman="org.dspace.core.ConfigurationManager" - exclude-result-prefixes="xalan encoder i18n dri mets dim xlink xsl util confman"> - - <xsl:output indent="yes"/> - - <!-- A collection rendered in the summaryList pattern. Encountered on the community-list page --> - <xsl:template name="collectionSummaryList-DIM"> - <xsl:variable name="data" select="./mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim"/> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="{@OBJID}"> - <span class="Z3988"> - <xsl:choose> - <xsl:when test="string-length($data/dim:field[@element='title'][1]) > 0"> - <xsl:value-of select="$data/dim:field[@element='title'][1]"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </span> - </a> - <!--Display community strengths (item counts) if they exist--> - <xsl:if test="string-length($data/dim:field[@element='format'][@qualifier='extent'][1]) > 0"> - <xsl:text> [</xsl:text> - <xsl:value-of select="$data/dim:field[@element='format'][@qualifier='extent'][1]"/> - <xsl:text>]</xsl:text> - </xsl:if> - </div> - <xsl:variable name="abstract" select="$data/dim:field[@element = 'description' and @qualifier='abstract']/node()"/> - <xsl:if test="$abstract and string-length($abstract[1]) > 0"> - <div class="artifact-info"> - <span class="short-description"> - <xsl:value-of select="util:shortenString($abstract, 220, 10)"/> - </span> - </div> - </xsl:if> - </div> - </xsl:template> - - <!-- A collection rendered in the detailList pattern. Encountered on the item view page as - the "this item is part of these collections" list --> - <xsl:template name="collectionDetailList-DIM"> - <xsl:variable name="data" select="./mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim"/> - <a href="{@OBJID}"> - <xsl:choose> - <xsl:when test="string-length($data/dim:field[@element='title'][1]) > 0"> - <xsl:value-of select="$data/dim:field[@element='title'][1]"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </a> - <!--Display collection strengths (item counts) if they exist--> - <xsl:if test="string-length($data/dim:field[@element='format'][@qualifier='extent'][1]) > 0"> - <xsl:text> [</xsl:text> - <xsl:value-of select="$data/dim:field[@element='format'][@qualifier='extent'][1]"/> - <xsl:text>]</xsl:text> - </xsl:if> - <br/> - <xsl:choose> - <xsl:when test="$data/dim:field[@element='description' and @qualifier='abstract']"> - <xsl:copy-of select="$data/dim:field[@element='description' and @qualifier='abstract']/node()"/> - </xsl:when> - <xsl:otherwise> - <xsl:copy-of select="$data/dim:field[@element='description'][1]/node()"/> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/community-list.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/community-list.xsl deleted file mode 100644 index e24f48dc4eef3864b0734e608db37cfc0ed64cce..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/community-list.xsl +++ /dev/null @@ -1,108 +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/ - ---> -<!-- - Rendering of a list of communities (e.g. on a community homepage, - or on the community-list page) - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet - xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:atom="http://www.w3.org/2005/Atom" - xmlns:ore="http://www.openarchives.org/ore/terms/" - xmlns:oreatom="http://www.openarchives.org/ore/atom/" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:xalan="http://xml.apache.org/xalan" - xmlns:encoder="xalan://java.net.URLEncoder" - xmlns:util="org.dspace.app.xmlui.utils.XSLUtils" - xmlns:confman="org.dspace.core.ConfigurationManager" - exclude-result-prefixes="xalan encoder i18n dri mets dim xlink xsl util confman"> - - <xsl:output indent="yes"/> - - <!-- A community rendered in the summaryList pattern. Encountered on the community-list and on - on the front page. --> - <xsl:template name="communitySummaryList-DIM"> - <xsl:variable name="data" select="./mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim"/> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="{@OBJID}"> - <span class="Z3988"> - <xsl:choose> - <xsl:when test="string-length($data/dim:field[@element='title'][1]) > 0"> - <xsl:value-of select="$data/dim:field[@element='title'][1]"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </span> - </a> - <!--Display community strengths (item counts) if they exist--> - <xsl:if test="string-length($data/dim:field[@element='format'][@qualifier='extent'][1]) > 0"> - <xsl:text> [</xsl:text> - <xsl:value-of select="$data/dim:field[@element='format'][@qualifier='extent'][1]"/> - <xsl:text>]</xsl:text> - </xsl:if> - </div> - <xsl:variable name="abstract" select="$data/dim:field[@element = 'description' and @qualifier='abstract']/node()"/> - <xsl:if test="$abstract and string-length($abstract[1]) > 0"> - <div class="artifact-info"> - <span class="short-description"> - <xsl:value-of select="util:shortenString($abstract, 220, 10)"/> - </span> - </div> - </xsl:if> - </div> - </xsl:template> - - <!-- A community rendered in the detailList pattern. Not currently used. --> - <xsl:template name="communityDetailList-DIM"> - <xsl:variable name="data" select="./mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim"/> - <span class="bold"> - <a href="{@OBJID}"> - <xsl:choose> - <xsl:when test="string-length($data/dim:field[@element='title'][1]) > 0"> - <xsl:value-of select="$data/dim:field[@element='title'][1]"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </a> - <!--Display community strengths (item counts) if they exist--> - <xsl:if test="string-length($data/dim:field[@element='format'][@qualifier='extent'][1]) > 0"> - <xsl:text> [</xsl:text> - <xsl:value-of select="$data/dim:field[@element='format'][@qualifier='extent'][1]"/> - <xsl:text>]</xsl:text> - </xsl:if> - <br/> - <xsl:choose> - <xsl:when test="$data/dim:field[@element='description' and @qualifier='abstract']"> - <xsl:copy-of select="$data/dim:field[@element='description' and @qualifier='abstract']/node()"/> - </xsl:when> - <xsl:otherwise> - <xsl:copy-of select="$data/dim:field[@element='description'][1]/node()"/> - </xsl:otherwise> - </xsl:choose> - </span> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-list.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-list.xsl deleted file mode 100644 index d39d4485234b4f5bcd6728713f17dc3baf48c002..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-list.xsl +++ /dev/null @@ -1,268 +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/ - ---> -<!-- - Rendering of a list of items (e.g. in a search or - browse results page) - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet - xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:atom="http://www.w3.org/2005/Atom" - xmlns:ore="http://www.openarchives.org/ore/terms/" - xmlns:oreatom="http://www.openarchives.org/ore/atom/" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:xalan="http://xml.apache.org/xalan" - xmlns:encoder="xalan://java.net.URLEncoder" - xmlns:util="org.dspace.app.xmlui.utils.XSLUtils" - xmlns:confman="org.dspace.core.ConfigurationManager" - exclude-result-prefixes="xalan encoder i18n dri mets dim xlink xsl util confman"> - - <xsl:output indent="yes"/> - - <!--these templates are modfied to support the 2 different item list views that - can be configured with the property 'xmlui.theme.mirage.item-list.emphasis' in dspace.cfg--> - - <xsl:template name="itemSummaryList-DIM"> - <xsl:variable name="itemWithdrawn" select="./mets:dmdSec/mets:mdWrap[@OTHERMDTYPE='DIM']/mets:xmlData/dim:dim/@withdrawn" /> - - <xsl:variable name="href"> - <xsl:choose> - <xsl:when test="$itemWithdrawn"> - <xsl:value-of select="@OBJEDIT"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="@OBJID"/> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:variable name="emphasis" select="confman:getProperty('xmlui.theme.mirage.item-list.emphasis')"/> - <xsl:choose> - <xsl:when test="'file' = $emphasis"> - - - <div class="item-wrapper clearfix"> - <xsl:apply-templates select="./mets:fileSec" mode="artifact-preview"><xsl:with-param name="href" select="$href"/></xsl:apply-templates> - <xsl:apply-templates select="./mets:dmdSec/mets:mdWrap[@OTHERMDTYPE='DIM']/mets:xmlData/dim:dim" - mode="itemSummaryList-DIM-file"><xsl:with-param name="href" select="$href"/></xsl:apply-templates> - </div> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates select="./mets:dmdSec/mets:mdWrap[@OTHERMDTYPE='DIM']/mets:xmlData/dim:dim" - mode="itemSummaryList-DIM-metadata"><xsl:with-param name="href" select="$href"/></xsl:apply-templates> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - - <!--handles the rendering of a single item in a list in file mode--> - <xsl:template match="dim:dim" mode="itemSummaryList-DIM-file"> - <xsl:param name="href"/> - <xsl:variable name="metadataWidth" select="675 - $thumbnail.maxwidth - 30"/> - <div class="item-metadata" style="width: {$metadataWidth}px;"> - <span class="bold"><i18n:text>xmlui.dri2xhtml.pioneer.title</i18n:text><xsl:text>:</xsl:text></span> - <span class="content" style="width: {$metadataWidth - 110}px;"> - <xsl:element name="a"> - <xsl:attribute name="href"> - <xsl:value-of select="$href"/> - </xsl:attribute> - <xsl:choose> - <xsl:when test="dim:field[@element='title']"> - <xsl:value-of select="dim:field[@element='title'][1]/node()"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </xsl:element> - </span> - <span class="Z3988"> - <xsl:attribute name="title"> - <xsl:call-template name="renderCOinS"/> - </xsl:attribute> -  <!-- non-breaking space to force separating the end tag --> - </span> - <span class="bold"><i18n:text>xmlui.dri2xhtml.pioneer.author</i18n:text><xsl:text>:</xsl:text></span> - <span class="content" style="width: {$metadataWidth - 110}px;"> - <xsl:choose> - <xsl:when test="dim:field[@element='contributor'][@qualifier='author']"> - <xsl:for-each select="dim:field[@element='contributor'][@qualifier='author']"> - <span> - <xsl:if test="@authority"> - <xsl:attribute name="class"> - <xsl:text>ds-dc_contributor_author-authority</xsl:text> - </xsl:attribute> - </xsl:if> - <xsl:copy-of select="node()"/> - </span> - <xsl:if test="count(following-sibling::dim:field[@element='contributor'][@qualifier='author']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='creator']"> - <xsl:for-each select="dim:field[@element='creator']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='creator']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='contributor']"> - <xsl:for-each select="dim:field[@element='contributor']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='contributor']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-author</i18n:text> - </xsl:otherwise> - </xsl:choose> - </span> - <xsl:if test="dim:field[@element='date' and @qualifier='issued'] or dim:field[@element='publisher']"> - <span class="bold"><i18n:text>xmlui.dri2xhtml.pioneer.date</i18n:text><xsl:text>:</xsl:text></span> - <span class="content" style="width: {$metadataWidth - 110}px;"> - <xsl:value-of - select="substring(dim:field[@element='date' and @qualifier='issued']/node(),1,10)"/> - </span> - </xsl:if> - </div> - </xsl:template> - - <!--handles the rendering of a single item in a list in metadata mode--> - <xsl:template match="dim:dim" mode="itemSummaryList-DIM-metadata"> - <xsl:param name="href"/> - <div class="artifact-description"> - <div class="artifact-title"> - <xsl:element name="a"> - <xsl:attribute name="href"> - <xsl:value-of select="$href"/> - </xsl:attribute> - <xsl:choose> - <xsl:when test="dim:field[@element='title']"> - <xsl:value-of select="dim:field[@element='title'][1]/node()"/> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </xsl:otherwise> - </xsl:choose> - </xsl:element> - <span class="Z3988"> - <xsl:attribute name="title"> - <xsl:call-template name="renderCOinS"/> - </xsl:attribute> -  <!-- non-breaking space to force separating the end tag --> - </span> - </div> - <div class="artifact-info"> - <span class="author"> - <xsl:choose> - <xsl:when test="dim:field[@element='contributor'][@qualifier='author']"> - <xsl:for-each select="dim:field[@element='contributor'][@qualifier='author']"> - <span> - <xsl:if test="@authority"> - <xsl:attribute name="class"><xsl:text>ds-dc_contributor_author-authority</xsl:text></xsl:attribute> - </xsl:if> - <xsl:copy-of select="node()"/> - </span> - <xsl:if test="count(following-sibling::dim:field[@element='contributor'][@qualifier='author']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='creator']"> - <xsl:for-each select="dim:field[@element='creator']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='creator']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='contributor']"> - <xsl:for-each select="dim:field[@element='contributor']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='contributor']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-author</i18n:text> - </xsl:otherwise> - </xsl:choose> - </span> - <xsl:text> </xsl:text> - <xsl:if test="dim:field[@element='date' and @qualifier='issued'] or dim:field[@element='publisher']"> - <span class="publisher-date"> - <xsl:text>(</xsl:text> - <xsl:if test="dim:field[@element='publisher']"> - <span class="publisher"> - <xsl:copy-of select="dim:field[@element='publisher']/node()"/> - </span> - <xsl:text>, </xsl:text> - </xsl:if> - <span class="date"> - <xsl:value-of select="substring(dim:field[@element='date' and @qualifier='issued']/node(),1,10)"/> - </span> - <xsl:text>)</xsl:text> - </span> - </xsl:if> - </div> - <xsl:if test="dim:field[@element = 'description' and @qualifier='abstract']"> - <xsl:variable name="abstract" select="dim:field[@element = 'description' and @qualifier='abstract']/node()"/> - <div class="artifact-abstract"> - <xsl:value-of select="util:shortenString($abstract, 220, 10)"/> - </div> - </xsl:if> - </div> - </xsl:template> - - <xsl:template name="itemDetailList-DIM"> - <xsl:call-template name="itemSummaryList-DIM"/> - </xsl:template> - - - <xsl:template match="mets:fileSec" mode="artifact-preview"> - <xsl:param name="href"/> - <div class="thumbnail-wrapper"> - <div class="artifact-preview"> - <a class="image-link" href="{$href}"> - <xsl:choose> - <xsl:when test="mets:fileGrp[@USE='THUMBNAIL']"> - <img alt="Thumbnail"> - <xsl:attribute name="src"> - <xsl:value-of - select="mets:fileGrp[@USE='THUMBNAIL']/mets:file/mets:FLocat[@LOCTYPE='URL']/@xlink:href"/> - </xsl:attribute> - </img> - </xsl:when> - <xsl:otherwise> - <img alt="Icon" src="{concat($theme-path, '/images/mime.png')}" style="height: {$thumbnail.maxheight}px;"/> - </xsl:otherwise> - </xsl:choose> - </a> - </div> - </div> - </xsl:template> - - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-view.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-view.xsl deleted file mode 100644 index 36fe11641265c6655f97217014ed890adb69d1ea..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/artifactbrowser/item-view.xsl +++ /dev/null @@ -1,539 +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/ - ---> -<!-- - Rendering specific to the item display page. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet - xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:atom="http://www.w3.org/2005/Atom" - xmlns:ore="http://www.openarchives.org/ore/terms/" - xmlns:oreatom="http://www.openarchives.org/ore/atom/" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:xalan="http://xml.apache.org/xalan" - xmlns:encoder="xalan://java.net.URLEncoder" - xmlns:util="org.dspace.app.xmlui.utils.XSLUtils" - xmlns:jstring="java.lang.String" - xmlns:rights="http://cosimo.stanford.edu/sdr/metsrights/" - exclude-result-prefixes="xalan encoder i18n dri mets dim xlink xsl util jstring rights"> - - <xsl:output indent="yes"/> - - <xsl:template name="itemSummaryView-DIM"> - <!-- Generate the info about the item from the metadata section --> - <xsl:apply-templates select="./mets:dmdSec/mets:mdWrap[@OTHERMDTYPE='DIM']/mets:xmlData/dim:dim" - mode="itemSummaryView-DIM"/> - - <xsl:copy-of select="$SFXLink" /> - <!-- Generate the bitstream information from the file section --> - <xsl:choose> - <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']/mets:file"> - <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CONTENT' or @USE='ORIGINAL']"> - <xsl:with-param name="context" select="."/> - <xsl:with-param name="primaryBitstream" select="./mets:structMap[@TYPE='LOGICAL']/mets:div[@TYPE='DSpace Item']/mets:fptr/@FILEID"/> - </xsl:apply-templates> - </xsl:when> - <!-- Special case for handling ORE resource maps stored as DSpace bitstreams --> - <xsl:when test="./mets:fileSec/mets:fileGrp[@USE='ORE']"> - <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='ORE']"/> - </xsl:when> - <xsl:otherwise> - <h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2> - <table class="ds-table file-list"> - <tr class="ds-table-header-row"> - <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-file</i18n:text></th> - <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text></th> - <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text></th> - <th><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-view</i18n:text></th> - </tr> - <tr> - <td colspan="4"> - <p><i18n:text>xmlui.dri2xhtml.METS-1.0.item-no-files</i18n:text></p> - </td> - </tr> - </table> - </xsl:otherwise> - </xsl:choose> - - <!-- Generate the Creative Commons license information from the file section (DSpace deposit license hidden by default)--> - <xsl:apply-templates select="./mets:fileSec/mets:fileGrp[@USE='CC-LICENSE']"/> - - </xsl:template> - - - <xsl:template match="dim:dim" mode="itemSummaryView-DIM"> - <div class="item-summary-view-metadata"> - <xsl:call-template name="itemSummaryView-DIM-fields"/> - </div> - </xsl:template> - - <xsl:template name="itemSummaryView-DIM-fields"> - <xsl:param name="clause" select="'1'"/> - <xsl:param name="phase" select="'even'"/> - <xsl:variable name="otherPhase"> - <xsl:choose> - <xsl:when test="$phase = 'even'"> - <xsl:text>odd</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>even</xsl:text> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - - <xsl:choose> - <!-- Title row --> - <xsl:when test="$clause = 1"> - - <xsl:choose> - <xsl:when test="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()"/> - </h1> - <div class="simple-item-view-other"> - <span class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-title</i18n:text>:</span> - <span> - <xsl:for-each select="dim:field[@element='title'][not(@qualifier)]"> - <xsl:value-of select="./node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='title'][not(@qualifier)]) != 0"> - <xsl:text>; </xsl:text> - <br/> - </xsl:if> - </xsl:for-each> - </span> - </div> - </xsl:when> - <xsl:when test="count(dim:field[@element='title'][not(@qualifier)]) = 1"> - <h1> - <xsl:value-of select="dim:field[@element='title'][not(@qualifier)][1]/node()"/> - </h1> - </xsl:when> - <xsl:otherwise> - <h1> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> - </h1> - </xsl:otherwise> - </xsl:choose> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </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'])"> - <div class="simple-item-view-authors"> - <xsl:choose> - <xsl:when test="dim:field[@element='contributor'][@qualifier='author']"> - <xsl:for-each select="dim:field[@element='contributor'][@qualifier='author']"> - <span> - <xsl:if test="@authority"> - <xsl:attribute name="class"><xsl:text>ds-dc_contributor_author-authority</xsl:text></xsl:attribute> - </xsl:if> - <xsl:copy-of select="node()"/> - </span> - <xsl:if test="count(following-sibling::dim:field[@element='contributor'][@qualifier='author']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='creator']"> - <xsl:for-each select="dim:field[@element='creator']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='creator']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:when test="dim:field[@element='contributor']"> - <xsl:for-each select="dim:field[@element='contributor']"> - <xsl:copy-of select="node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='contributor']) != 0"> - <xsl:text>; </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.METS-1.0.no-author</i18n:text> - </xsl:otherwise> - </xsl:choose> - </div> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </xsl:when> - - <!-- identifier.uri row --> - <xsl:when test="$clause = 3 and (dim:field[@element='identifier' and @qualifier='uri'])"> - <div class="simple-item-view-other"> - <span class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-uri</i18n:text>:</span> - <span> - <xsl:for-each select="dim:field[@element='identifier' and @qualifier='uri']"> - <a> - <xsl:attribute name="href"> - <xsl:copy-of select="./node()"/> - </xsl:attribute> - <xsl:copy-of select="./node()"/> - </a> - <xsl:if test="count(following-sibling::dim:field[@element='identifier' and @qualifier='uri']) != 0"> - <br/> - </xsl:if> - </xsl:for-each> - </span> - </div> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </xsl:when> - - <!-- date.issued row --> - <xsl:when test="$clause = 4 and (dim:field[@element='date' and @qualifier='issued'])"> - <div class="simple-item-view-other"> - <span class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-date</i18n:text>:</span> - <span> - <xsl:for-each select="dim:field[@element='date' and @qualifier='issued']"> - <xsl:copy-of select="substring(./node(),1,10)"/> - <xsl:if test="count(following-sibling::dim:field[@element='date' and @qualifier='issued']) != 0"> - <br/> - </xsl:if> - </xsl:for-each> - </span> - </div> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </xsl:when> - - <!-- Abstract row --> - <xsl:when test="$clause = 5 and (dim:field[@element='description' and @qualifier='abstract' and descendant::text()])"> - <div class="simple-item-view-description"> - <h3><i18n:text>xmlui.dri2xhtml.METS-1.0.item-abstract</i18n:text>:</h3> - <div> - <xsl:if test="count(dim:field[@element='description' and @qualifier='abstract']) > 1"> - <div class="spacer"> </div> - </xsl:if> - <xsl:for-each select="dim:field[@element='description' and @qualifier='abstract']"> - <xsl:choose> - <xsl:when test="node()"> - <xsl:copy-of select="node()"/> - </xsl:when> - <xsl:otherwise> - <xsl:text> </xsl:text> - </xsl:otherwise> - </xsl:choose> - <xsl:if test="count(following-sibling::dim:field[@element='description' and @qualifier='abstract']) != 0"> - <div class="spacer"> </div> - </xsl:if> - </xsl:for-each> - <xsl:if test="count(dim:field[@element='description' and @qualifier='abstract']) > 1"> - <div class="spacer"> </div> - </xsl:if> - </div> - </div> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </xsl:when> - - <!-- Description row --> - <xsl:when test="$clause = 6 and (dim:field[@element='description' and not(@qualifier)])"> - <div class="simple-item-view-description"> - <h3 class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-description</i18n:text>:</h3> - <div> - <xsl:if test="count(dim:field[@element='description' and not(@qualifier)]) > 1 and not(count(dim:field[@element='description' and @qualifier='abstract']) > 1)"> - <div class="spacer"> </div> - </xsl:if> - <xsl:for-each select="dim:field[@element='description' and not(@qualifier)]"> - <xsl:copy-of select="./node()"/> - <xsl:if test="count(following-sibling::dim:field[@element='description' and not(@qualifier)]) != 0"> - <div class="spacer"> </div> - </xsl:if> - </xsl:for-each> - <xsl:if test="count(dim:field[@element='description' and not(@qualifier)]) > 1"> - <div class="spacer"> </div> - </xsl:if> - </div> - </div> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$otherPhase"/> - </xsl:call-template> - </xsl:when> - - <xsl:when test="$clause = 7 and $ds_item_view_toggle_url != ''"> - <p class="ds-paragraph item-view-toggle item-view-toggle-bottom"> - <a> - <xsl:attribute name="href"><xsl:value-of select="$ds_item_view_toggle_url"/></xsl:attribute> - <i18n:text>xmlui.ArtifactBrowser.ItemViewer.show_full</i18n:text> - </a> - </p> - </xsl:when> - - <!-- recurse without changing phase if we didn't output anything --> - <xsl:otherwise> - <!-- IMPORTANT: This test should be updated if clauses are added! --> - <xsl:if test="$clause < 8"> - <xsl:call-template name="itemSummaryView-DIM-fields"> - <xsl:with-param name="clause" select="($clause + 1)"/> - <xsl:with-param name="phase" select="$phase"/> - </xsl:call-template> - </xsl:if> - </xsl:otherwise> - </xsl:choose> - - <!-- Generate the Creative Commons license information from the file section (DSpace deposit license hidden by default) --> - <xsl:apply-templates select="mets:fileSec/mets:fileGrp[@USE='CC-LICENSE']"/> - </xsl:template> - - - <xsl:template match="dim:dim" mode="itemDetailView-DIM"> - <table class="ds-includeSet-table detailtable"> - <xsl:apply-templates mode="itemDetailView-DIM"/> - </table> - <span class="Z3988"> - <xsl:attribute name="title"> - <xsl:call-template name="renderCOinS"/> - </xsl:attribute> -  <!-- non-breaking space to force separating the end tag --> - </span> - <xsl:copy-of select="$SFXLink" /> - </xsl:template> - - <xsl:template match="dim:field" mode="itemDetailView-DIM"> - <tr> - <xsl:attribute name="class"> - <xsl:text>ds-table-row </xsl:text> - <xsl:if test="(position() div 2 mod 2 = 0)">even </xsl:if> - <xsl:if test="(position() div 2 mod 2 = 1)">odd </xsl:if> - </xsl:attribute> - <td class="label-cell"> - <xsl:value-of select="./@mdschema"/> - <xsl:text>.</xsl:text> - <xsl:value-of select="./@element"/> - <xsl:if test="./@qualifier"> - <xsl:text>.</xsl:text> - <xsl:value-of select="./@qualifier"/> - </xsl:if> - </td> - <td> - <xsl:copy-of select="./node()"/> - <xsl:if test="./@authority and ./@confidence"> - <xsl:call-template name="authorityConfidenceIcon"> - <xsl:with-param name="confidence" select="./@confidence"/> - </xsl:call-template> - </xsl:if> - </td> - <td><xsl:value-of select="./@language"/></td> - </tr> - </xsl:template> - - <!-- don't render the item-view-toggle automatically in the summary view, only when it gets called --> - <xsl:template match="dri:p[contains(@rend , 'item-view-toggle') and - (preceding-sibling::dri:referenceSet[@type = 'summaryView'] or following-sibling::dri:referenceSet[@type = 'summaryView'])]"> - </xsl:template> - - <!-- don't render the head on the item view page --> - <xsl:template match="dri:div[@n='item-view']/dri:head" priority="5"> - </xsl:template> - - <xsl:template match="mets:fileGrp[@USE='CONTENT']"> - <xsl:param name="context"/> - <xsl:param name="primaryBitstream" select="-1"/> - - <h2><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-head</i18n:text></h2> - <div class="file-list"> - <xsl:choose> - <!-- If one exists and it's of text/html MIME type, only display the primary bitstream --> - <xsl:when test="mets:file[@ID=$primaryBitstream]/@MIMETYPE='text/html'"> - <xsl:apply-templates select="mets:file[@ID=$primaryBitstream]"> - <xsl:with-param name="context" select="$context"/> - </xsl:apply-templates> - </xsl:when> - <!-- Otherwise, iterate over and display all of them --> - <xsl:otherwise> - <xsl:apply-templates select="mets:file"> - <!--Do not sort any more bitstream order can be changed--> - <!--<xsl:sort data-type="number" select="boolean(./@ID=$primaryBitstream)" order="descending" />--> - <!--<xsl:sort select="mets:FLocat[@LOCTYPE='URL']/@xlink:title"/>--> - <xsl:with-param name="context" select="$context"/> - </xsl:apply-templates> - </xsl:otherwise> - </xsl:choose> - </div> - </xsl:template> - - <xsl:template match="mets:file"> - <xsl:param name="context" select="."/> - <div class="file-wrapper clearfix"> - <div class="thumbnail-wrapper"> - <a class="image-link"> - <xsl:attribute name="href"> - <xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:href"/> - </xsl:attribute> - <xsl:choose> - <xsl:when test="$context/mets:fileSec/mets:fileGrp[@USE='THUMBNAIL']/ - mets:file[@GROUPID=current()/@GROUPID]"> - <img alt="Thumbnail"> - <xsl:attribute name="src"> - <xsl:value-of select="$context/mets:fileSec/mets:fileGrp[@USE='THUMBNAIL']/ - mets:file[@GROUPID=current()/@GROUPID]/mets:FLocat[@LOCTYPE='URL']/@xlink:href"/> - </xsl:attribute> - </img> - </xsl:when> - <xsl:otherwise> - <img alt="Icon" src="{concat($theme-path, '/images/mime.png')}" style="height: {$thumbnail.maxheight}px;"/> - </xsl:otherwise> - </xsl:choose> - </a> - </div> - <div class="file-metadata" style="height: {$thumbnail.maxheight}px;"> - <div> - <span class="bold"> - <i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-name</i18n:text> - <xsl:text>:</xsl:text> - </span> - <span> - <xsl:attribute name="title"><xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:title"/></xsl:attribute> - <xsl:value-of select="util:shortenString(mets:FLocat[@LOCTYPE='URL']/@xlink:title, 17, 5)"/> - </span> - </div> - <!-- File size always comes in bytes and thus needs conversion --> - <div> - <span class="bold"> - <i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-size</i18n:text> - <xsl:text>:</xsl:text> - </span> - <span> - <xsl:choose> - <xsl:when test="@SIZE < 1024"> - <xsl:value-of select="@SIZE"/> - <i18n:text>xmlui.dri2xhtml.METS-1.0.size-bytes</i18n:text> - </xsl:when> - <xsl:when test="@SIZE < 1024 * 1024"> - <xsl:value-of select="substring(string(@SIZE div 1024),1,5)"/> - <i18n:text>xmlui.dri2xhtml.METS-1.0.size-kilobytes</i18n:text> - </xsl:when> - <xsl:when test="@SIZE < 1024 * 1024 * 1024"> - <xsl:value-of select="substring(string(@SIZE div (1024 * 1024)),1,5)"/> - <i18n:text>xmlui.dri2xhtml.METS-1.0.size-megabytes</i18n:text> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="substring(string(@SIZE div (1024 * 1024 * 1024)),1,5)"/> - <i18n:text>xmlui.dri2xhtml.METS-1.0.size-gigabytes</i18n:text> - </xsl:otherwise> - </xsl:choose> - </span> - </div> - <!-- Lookup File Type description in local messages.xml based on MIME Type. - In the original DSpace, this would get resolved to an application via - the Bitstream Registry, but we are constrained by the capabilities of METS - and can't really pass that info through. --> - <div> - <span class="bold"> - <i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-format</i18n:text> - <xsl:text>:</xsl:text> - </span> - <span> - <xsl:call-template name="getFileTypeDesc"> - <xsl:with-param name="mimetype"> - <xsl:value-of select="substring-before(@MIMETYPE,'/')"/> - <xsl:text>/</xsl:text> - <xsl:value-of select="substring-after(@MIMETYPE,'/')"/> - </xsl:with-param> - </xsl:call-template> - </span> - </div> - <!----> - <!-- Display the contents of 'Description' only if bitstream contains a description --> - <xsl:if test="mets:FLocat[@LOCTYPE='URL']/@xlink:label != ''"> - <div> - <span class="bold"> - <i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-description</i18n:text> - <xsl:text>:</xsl:text> - </span> - <span> - <xsl:attribute name="title"><xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:label"/></xsl:attribute> - <!--<xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:label"/>--> - <xsl:value-of select="util:shortenString(mets:FLocat[@LOCTYPE='URL']/@xlink:label, 17, 5)"/> - </span> - </div> - </xsl:if> - </div> - <div class="file-link" style="height: {$thumbnail.maxheight}px;"> - <xsl:choose> - <xsl:when test="@ADMID"> - <xsl:call-template name="display-rights"/> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name="view-open"/> - </xsl:otherwise> - </xsl:choose> - </div> - </div> - </xsl:template> - - <xsl:template name="view-open"> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:href"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-viewOpen</i18n:text> - </a> - </xsl:template> - - <xsl:template name="display-rights"> - <xsl:variable name="file_id" select="jstring:replaceAll(jstring:replaceAll(string(@ADMID), '_METSRIGHTS', ''), 'rightsMD_', '')"/> - <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: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}"/> - <!-- icon source: http://commons.wikimedia.org/wiki/File:Crystal_Clear_action_lock3.png --> - </a> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name="view-open"/> - </xsl:otherwise> - </xsl:choose> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/general/choice-authority-control.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/general/choice-authority-control.xsl deleted file mode 100644 index cb5db51ce0da55f62e1d17983eec5640a02353b5..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/aspect/general/choice-authority-control.xsl +++ /dev/null @@ -1,410 +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/ - ---> -<!-- - Rendering of the authority control related pages. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!-- =============================================================== --> - <!-- - - - - - New templates for Choice/Authority control - - - - - --> - - <!-- choose 'hidden' for invisible auth, 'text' lets CSS control it. --> - <xsl:variable name="authorityInputType" select="'text'"/> - - <!-- add button to invoke Choices lookup popup.. assume - - that the context is a dri:field, where dri:params/@choices is true. - --> - <xsl:template name="addLookupButton"> - <xsl:param name="isName" select="'missing value'"/> - <!-- optional param if you want to send authority value to diff field --> - <xsl:param name="authorityInput" select="concat(@n,'_authority')"/> - <!-- optional param for confidence indicator ID --> - <xsl:param name="confIndicator" select="''"/> - <input type="button" name="{concat('lookup_',@n)}" class="ds-button-field ds-add-button" > - <xsl:attribute name="value"> - <xsl:text>Lookup</xsl:text> - <xsl:if test="contains(dri:params/@operations,'add')"> - <xsl:text> & Add</xsl:text> - </xsl:if> - </xsl:attribute> - <xsl:attribute name="onClick"> - <xsl:text>javascript:DSpaceChoiceLookup('</xsl:text> - <!-- URL --> - <xsl:value-of select="concat($context-path,'/admin/lookup')"/> - <xsl:text>', '</xsl:text> - <!-- field --> - <xsl:value-of select="dri:params/@choices"/> - <xsl:text>', '</xsl:text> - <!-- formID --> - <xsl:value-of select="translate(ancestor::dri:div[@interactive='yes']/@id,'.','_')"/> - <xsl:text>', '</xsl:text> - <!-- valueInput --> - <xsl:value-of select="@n"/> - <xsl:text>', '</xsl:text> - <!-- authorityInput, name of field to get authority --> - <xsl:value-of select="$authorityInput"/> - <xsl:text>', '</xsl:text> - <!-- Confidence Indicator's ID so lookup can frob it --> - <xsl:value-of select="$confIndicator"/> - <xsl:text>', </xsl:text> - <!-- Collection ID for context --> - <xsl:choose> - <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='choice'][@qualifier='collection']"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='choice'][@qualifier='collection']"/> - </xsl:when> - <xsl:otherwise> - <xsl:text>-1</xsl:text> - </xsl:otherwise> - </xsl:choose> - <xsl:text>, </xsl:text> - <!-- isName --> - <xsl:value-of select="$isName"/> - <xsl:text>, </xsl:text> - <!-- isRepating --> - <xsl:value-of select="boolean(contains(dri:params/@operations,'add'))"/> - <xsl:text>);</xsl:text> - </xsl:attribute> - </input> - </xsl:template> - - <!-- Fragment to display an authority confidence icon. - - Insert an invisible 1x1 image which gets "covered" by background - - image as dictated by the CSS, so icons are easily adjusted in CSS. - - "confidence" param is confidence _value_, i.e. symbolic name - --> - <xsl:template name="authorityConfidenceIcon"> - <!-- default confidence value won't show any image. --> - <xsl:param name="confidence" select="'blank'"/> - <xsl:param name="id" select="''"/> - <xsl:variable name="lcConfidence" select="translate($confidence,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')"/> - <img i18n:attr="title"> - <xsl:if test="string-length($id) > 0"> - <xsl:attribute name="id"> - <xsl:value-of select="$id"/> - </xsl:attribute> - </xsl:if> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/authority_control/invisible.gif')"/> - </xsl:attribute> - <xsl:attribute name="class"> - <xsl:text>ds-authority-confidence </xsl:text> - <xsl:choose> - <xsl:when test="string-length($lcConfidence) > 0"> - <xsl:value-of select="concat('cf-',$lcConfidence,' ')"/> - </xsl:when> - <xsl:otherwise> - <xsl:text>cf-blank </xsl:text> - </xsl:otherwise> - </xsl:choose> - </xsl:attribute> - <xsl:attribute name="title"> - <xsl:text>xmlui.authority.confidence.description.cf_</xsl:text> - <xsl:value-of select="$lcConfidence"/> - </xsl:attribute> - </img> - </xsl:template> - - <!-- Fragment to include an authority confidence hidden input - - assumes @n is the name of the field. - - param is confidence _value_, i.e. integer 0-6 - --> - <xsl:template name="authorityConfidenceInput"> - <xsl:param name="confidence"/> - <xsl:param name="name"/> - <input class="ds-authority-confidence-input" type="hidden"> - <xsl:attribute name="name"> - <xsl:value-of select="$name"/> - </xsl:attribute> - <xsl:attribute name="value"> - <xsl:value-of select="$confidence"/> - </xsl:attribute> - </input> - </xsl:template> - - - <!-- insert fields needed by Scriptaculous autocomplete --> - <xsl:template name="addAuthorityAutocompleteWidgets"> - <!-- "spinner" indicator to signal "loading", managed by autocompleter --> - <!-- put it next to input field --> - <span style="display:none;"> - <xsl:attribute name="id"> - <xsl:value-of select="concat(translate(@id,'.','_'),'_indicator')"/> - </xsl:attribute> - <img alt="Loading..."> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/authority_control/suggest-indicator.gif')"/> - </xsl:attribute> - </img> - </span> - <!-- This is the anchor for autocomplete popup, div id="..._container" --> - <!-- put it below input field, give ID to autocomplete below --> - <div class="autocomplete"> - <xsl:attribute name="id"> - <xsl:value-of select="concat(translate(@id,'.','_'),'_container')"/> - </xsl:attribute> - <xsl:text> </xsl:text> - </div> - </xsl:template> - - <!-- adds autocomplete fields and setup script to "normal" submit input --> - <xsl:template name="addAuthorityAutocomplete"> - <xsl:param name="confidenceIndicatorID" select="''"/> - <xsl:param name="confidenceName" select="''"/> - <xsl:call-template name="addAuthorityAutocompleteWidgets"/> - <xsl:call-template name="autocompleteSetup"> - <xsl:with-param name="formID" select="translate(ancestor::dri:div[@interactive='yes']/@id,'.','_')"/> - <xsl:with-param name="metadataField" select="@n"/> - <xsl:with-param name="inputName" select="@n"/> - <xsl:with-param name="authorityName" select="concat(@n,'_authority')"/> - <xsl:with-param name="containerID" select="concat(translate(@id,'.','_'),'_container')"/> - <xsl:with-param name="indicatorID" select="concat(translate(@id,'.','_'),'_indicator')"/> - <xsl:with-param name="isClosed" select="contains(dri:params/@choicesClosed,'true')"/> - <xsl:with-param name="confidenceIndicatorID" select="$confidenceIndicatorID"/> - <xsl:with-param name="confidenceName" select="$confidenceName"/> - <xsl:with-param name="collectionID"> - <xsl:choose> - <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='choice'][@qualifier='collection']"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='choice'][@qualifier='collection']"/> - </xsl:when> - <xsl:otherwise> - <xsl:text>-1</xsl:text> - </xsl:otherwise> - </xsl:choose> - </xsl:with-param> - </xsl:call-template> - </xsl:template> - - <!-- generate the script that sets up autocomplete feature on input field --> - <!-- ..it has lots of params --> - <xsl:template name="autocompleteSetup"> - <xsl:param name="formID" select="'missing value'"/> - <xsl:param name="metadataField" select="'missing value'"/> - <xsl:param name="inputName" select="'missing value'"/> - <xsl:param name="authorityName" select="''"/> - <xsl:param name="containerID" select="'missing value'"/> - <xsl:param name="collectionID" select="'-1'"/> - <xsl:param name="indicatorID" select="'missing value'"/> - <xsl:param name="confidenceIndicatorID" select="''"/> - <xsl:param name="confidenceName" select="''"/> - <xsl:param name="isClosed" select="'false'"/> - <script type="text/javascript"> - <xsl:text>runAfterJSImports.add(function() {</xsl:text> - <xsl:text>$(document).ready(function() {</xsl:text> - <xsl:text>var gigo = DSpaceSetupAutocomplete('</xsl:text> - <xsl:value-of select="$formID"/> - <xsl:text>', { metadataField: '</xsl:text> - <xsl:value-of select="$metadataField"/> - <xsl:text>', isClosed: '</xsl:text> - <xsl:value-of select="$isClosed"/> - <xsl:text>', inputName: '</xsl:text> - <xsl:value-of select="$inputName"/> - <xsl:text>', authorityName: '</xsl:text> - <xsl:value-of select="$authorityName"/> - <xsl:text>', containerID: '</xsl:text> - <xsl:value-of select="$containerID"/> - <xsl:text>', indicatorID: '</xsl:text> - <xsl:value-of select="$indicatorID"/> - <xsl:text>', confidenceIndicatorID: '</xsl:text> - <xsl:value-of select="$confidenceIndicatorID"/> - <xsl:text>', confidenceName: '</xsl:text> - <xsl:value-of select="$confidenceName"/> - <xsl:text>', collection: </xsl:text> - <xsl:value-of select="$collectionID"/> - <xsl:text>, contextPath: '</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>'});</xsl:text> - <xsl:text>});</xsl:text> - <xsl:text>});</xsl:text> - </script> - </xsl:template> - - <!-- add the extra _authority{_n?} and _confidence input fields --> - <xsl:template name="authorityInputFields"> - <xsl:param name="name" select="''"/> - <xsl:param name="id" select="''"/> - <xsl:param name="position" select="''"/> - <xsl:param name="authValue" select="''"/> - <xsl:param name="confValue" select="''"/> - <xsl:param name="confIndicatorID" select="''"/> - <xsl:param name="unlockButton" select="''"/> - <xsl:param name="unlockHelp" select="''"/> - <xsl:variable name="authFieldID" select="concat(translate(@id,'.','_'),'_authority')"/> - <xsl:variable name="confFieldID" select="concat(translate(@id,'.','_'),'_confidence')"/> - <!-- the authority key value --> - <input> - <xsl:attribute name="class"> - <xsl:text>ds-authority-value </xsl:text> - <xsl:if test="$unlockButton"> - <xsl:text>ds-authority-visible </xsl:text> - </xsl:if> - </xsl:attribute> - <xsl:attribute name="type"><xsl:value-of select="$authorityInputType"/></xsl:attribute> - <xsl:attribute name="readonly"><xsl:text>readonly</xsl:text></xsl:attribute> - <xsl:attribute name="name"> - <xsl:value-of select="concat($name,'_authority')"/> - <xsl:if test="$position"> - <xsl:value-of select="concat('_', $position)"/> - </xsl:if> - </xsl:attribute> - <xsl:if test="$id"> - <xsl:attribute name="id"> - <xsl:value-of select="$authFieldID"/> - </xsl:attribute> - </xsl:if> - <xsl:attribute name="value"> - <xsl:value-of select="$authValue"/> - </xsl:attribute> - <!-- this updates confidence after a manual change to authority value --> - <xsl:attribute name="onChange"> - <xsl:text>javascript: return DSpaceAuthorityOnChange(this, '</xsl:text> - <xsl:value-of select="$confFieldID"/> - <xsl:text>','</xsl:text> - <xsl:value-of select="$confIndicatorID"/> - <xsl:text>');</xsl:text> - </xsl:attribute> - </input> - <!-- optional "unlock" button on (visible) authority value field --> - <xsl:if test="$unlockButton"> - <input type="image" class="ds-authority-lock is-locked " value=""> - <xsl:attribute name="onClick"> - <xsl:text>javascript: return DSpaceToggleAuthorityLock(this, '</xsl:text> - <xsl:value-of select="$authFieldID"/> - <xsl:text>');</xsl:text> - </xsl:attribute> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/authority_control/invisible.gif')"/> - </xsl:attribute> - <xsl:attribute name="i18n:attr">title</xsl:attribute> - <xsl:attribute name="title"> - <xsl:value-of select="$unlockHelp"/> - </xsl:attribute> - </input> - </xsl:if> - <input class="ds-authority-confidence-input" type="hidden"> - <xsl:attribute name="name"> - <xsl:value-of select="concat($name,'_confidence')"/> - <xsl:if test="$position"> - <xsl:value-of select="concat('_', $position)"/> - </xsl:if> - </xsl:attribute> - <xsl:if test="$id"> - <xsl:attribute name="id"> - <xsl:value-of select="$confFieldID"/> - </xsl:attribute> - </xsl:if> - <xsl:attribute name="value"> - <xsl:value-of select="$confValue"/> - </xsl:attribute> - </input> - </xsl:template> - - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> - <!-- Special Transformations for Choice Authority lookup popup page --> - - <!-- indicator spinner --> - <xsl:template match="dri:item[@id='aspect.general.ChoiceLookupTransformer.item.select']/dri:figure"> - <img id="lookup_indicator_id" alt="Loading..." style="display:none;"> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/authority_control/lookup-indicator.gif')"/> - </xsl:attribute> - </img> - </xsl:template> - - <!-- This inline JS must be added to the popup page for choice lookups --> - <xsl:template name="choiceLookupPopUpSetup"> - <script type="text/javascript"> - var form = document.getElementById('aspect_general_ChoiceLookupTransformer_div_lookup'); - DSpaceChoicesSetup(form); - </script> - </xsl:template> - - <!-- Special select widget for lookup popup --> - <xsl:template match="dri:field[@id='aspect.general.ChoiceLookupTransformer.field.chooser']"> - <div> - <select onChange="javascript:DSpaceChoicesSelectOnChange();"> - <xsl:call-template name="fieldAttributes"/> - <xsl:apply-templates/> - <xsl:comment>space filler because "unclosed" select annoys browsers</xsl:comment> - </select> - <img class="choices-lookup" id="lookup_indicator_id" alt="Loading..." style="display:none;"> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/authority_control/lookup-indicator.gif')"/> - </xsl:attribute> - </img> - </div> - </xsl:template> - - <!-- Generate buttons with onClick attribute, since it is the easiest - - way to set a single event handler in a browser-independent manner. - --> - - <!-- choice popup "accept" button --> - <xsl:template match="dri:field[@id='aspect.general.ChoiceLookupTransformer.field.accept']"> - <xsl:call-template name="choiceLookupButton"> - <xsl:with-param name="onClick" select="'javascript:DSpaceChoicesAcceptOnClick();'"/> - </xsl:call-template> - </xsl:template> - - <!-- choice popup "more" button --> - <xsl:template match="dri:field[@id='aspect.general.ChoiceLookupTransformer.field.more']"> - <xsl:call-template name="choiceLookupButton"> - <xsl:with-param name="onClick" select="'javascript:DSpaceChoicesMoreOnClick();'"/> - </xsl:call-template> - </xsl:template> - - <!-- choice popup "cancel" button --> - <xsl:template match="dri:field[@id='aspect.general.ChoiceLookupTransformer.field.cancel']"> - <xsl:call-template name="choiceLookupButton"> - <xsl:with-param name="onClick" select="'javascript:DSpaceChoicesCancelOnClick();'"/> - </xsl:call-template> - </xsl:template> - - <!-- button markup: special handling needed because these must not be <input type=submit> --> - <xsl:template name="choiceLookupButton"> - <xsl:param name="onClick"/> - <input type="button" onClick="{$onClick}"> - <xsl:call-template name="fieldAttributes"/> - <xsl:attribute name="value"> - <xsl:choose> - <xsl:when test="./dri:value[@type='raw']"> - <xsl:value-of select="./dri:value[@type='raw']"/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="./dri:value[@type='default']"/> - </xsl:otherwise> - </xsl:choose> - </xsl:attribute> - <xsl:if test="dri:value/i18n:text"> - <xsl:attribute name="i18n:attr">value</xsl:attribute> - </xsl:if> - <xsl:apply-templates /> - </input> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/attribute-handlers.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/attribute-handlers.xsl deleted file mode 100644 index 678ecfbe48dddf9b2f501a7c2a77671fc56dbdcf..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/attribute-handlers.xsl +++ /dev/null @@ -1,208 +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/ - ---> -<!-- - Templates to cover the attribute calls. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <xsl:template match="@pagination"> - <xsl:param name="position"/> - <xsl:choose> - <xsl:when test=". = 'simple'"> - <div class="pagination clearfix {$position}"> - <p class="pagination-info"> - <i18n:translate> - <xsl:choose> - <xsl:when test="parent::node()/@itemsTotal = -1"> - <i18n:text>xmlui.dri2xhtml.structural.pagination-info.nototal</i18n:text> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.structural.pagination-info</i18n:text> - </xsl:otherwise> - </xsl:choose> - <i18n:param><xsl:value-of select="parent::node()/@firstItemIndex"/></i18n:param> - <i18n:param><xsl:value-of select="parent::node()/@lastItemIndex"/></i18n:param> - <i18n:param><xsl:value-of select="parent::node()/@itemsTotal"/></i18n:param> - </i18n:translate> - <!-- - <xsl:text>Now showing items </xsl:text> - <xsl:value-of select="parent::node()/@firstItemIndex"/> - <xsl:text>-</xsl:text> - <xsl:value-of select="parent::node()/@lastItemIndex"/> - <xsl:text> of </xsl:text> - <xsl:value-of select="parent::node()/@itemsTotal"/> - --> - </p> - <ul class="pagination-links"> - <li> - <xsl:if test="parent::node()/@previousPage"> - <a class="previous-page-link"> - <xsl:attribute name="href"> - <xsl:value-of select="parent::node()/@previousPage"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.pagination-previous</i18n:text> - </a> - </xsl:if> - </li> - <li> - <xsl:if test="parent::node()/@nextPage"> - <a class="next-page-link"> - <xsl:attribute name="href"> - <xsl:value-of select="parent::node()/@nextPage"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.pagination-next</i18n:text> - </a> - </xsl:if> - </li> - </ul> - </div> - </xsl:when> - <xsl:when test=". = 'masked'"> - <div class="pagination-masked clearfix {$position}"> - <p class="pagination-info"> - <i18n:translate> - <xsl:choose> - <xsl:when test="parent::node()/@itemsTotal = -1"> - <i18n:text>xmlui.dri2xhtml.structural.pagination-info.nototal</i18n:text> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.structural.pagination-info</i18n:text> - </xsl:otherwise> - </xsl:choose> - <i18n:param><xsl:value-of select="parent::node()/@firstItemIndex"/></i18n:param> - <i18n:param><xsl:value-of select="parent::node()/@lastItemIndex"/></i18n:param> - <i18n:param><xsl:value-of select="parent::node()/@itemsTotal"/></i18n:param> - </i18n:translate> - </p> - <ul class="pagination-links"> - <xsl:if test="not(parent::node()/@firstItemIndex = 0 or parent::node()/@firstItemIndex = 1)"> - <li> - <a class="previous-page-link"> - <xsl:attribute name="href"> - <xsl:value-of - select="substring-before(parent::node()/@pageURLMask,'{pageNum}')"/> - <xsl:value-of select="parent::node()/@currentPage - 1"/> - <xsl:value-of - select="substring-after(parent::node()/@pageURLMask,'{pageNum}')"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.pagination-previous</i18n:text> - </a> - </li> - </xsl:if> - <xsl:if test="(parent::node()/@currentPage - 4) > 0"> - <li class="first-page-link"> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="substring-before(parent::node()/@pageURLMask,'{pageNum}')"/> - <xsl:text>1</xsl:text> - <xsl:value-of select="substring-after(parent::node()/@pageURLMask,'{pageNum}')"/> - </xsl:attribute> - <xsl:text>1</xsl:text> - </a> - <xsl:text> . . . </xsl:text> - </li> - </xsl:if> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">-3</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">-2</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">-1</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">0</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">1</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">2</xsl:with-param> - </xsl:call-template> - <xsl:call-template name="offset-link"> - <xsl:with-param name="pageOffset">3</xsl:with-param> - </xsl:call-template> - <xsl:if test="(parent::node()/@currentPage + 4) <= (parent::node()/@pagesTotal)"> - <li> - <xsl:text>. . .</xsl:text> - </li> - <li class="last-page-link"> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="substring-before(parent::node()/@pageURLMask,'{pageNum}')"/> - <xsl:value-of select="parent::node()/@pagesTotal"/> - <xsl:value-of select="substring-after(parent::node()/@pageURLMask,'{pageNum}')"/> - </xsl:attribute> - <xsl:value-of select="parent::node()/@pagesTotal"/> - </a> - </li> - </xsl:if> - <xsl:if test="not(parent::node()/@lastItemIndex = parent::node()/@itemsTotal)"> - <li> - <a class="next-page-link"> - <xsl:attribute name="href"> - <xsl:value-of - select="substring-before(parent::node()/@pageURLMask,'{pageNum}')"/> - <xsl:value-of select="parent::node()/@currentPage + 1"/> - <xsl:value-of - select="substring-after(parent::node()/@pageURLMask,'{pageNum}')"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.pagination-next</i18n:text> - </a> - </li> - </xsl:if> - - </ul> - <xsl:if test="parent::node()/dri:div[@n = 'masked-page-control']"> - <xsl:apply-templates select="parent::node()/dri:div[@n='masked-page-control']/dri:div"> - <xsl:with-param name="position" select="$position"/> - </xsl:apply-templates> - </xsl:if> - </div> - </xsl:when> - </xsl:choose> - </xsl:template> - - <xsl:template match="dri:div[@n = 'masked-page-control']"> - <!--Do not render this division, this is handled by the xsl--> - </xsl:template> - - <xsl:template match="dri:div[@n ='search-controls-gear']"> - <xsl:param name="position"/> - <div> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class"><xsl:value-of select="$position"/></xsl:with-param> - </xsl:call-template> - - <xsl:apply-templates/> - </div> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/elements.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/elements.xsl deleted file mode 100644 index 971932a6049902c468b8c93a8ff850b966d4d9e7..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/elements.xsl +++ /dev/null @@ -1,95 +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/ - ---> -<!-- - Templates to cover the common dri elements. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!--Removed the automatic font sizing for headers, because while I liked the idea, - in practice it's too unpredictable. - Also made all head's follow the same rule: count the number of ancestors that have - a head, that's the number after the 'h' in the tagname--> - <xsl:template name="renderHead"> - <xsl:param name="class"/> - <xsl:variable name="head_count" select="count(ancestor::dri:*[dri:head])"/> - <xsl:element name="h{$head_count}"> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class" select="$class"/> - </xsl:call-template> - <xsl:apply-templates /> - </xsl:element> - </xsl:template> - - - <xsl:template match="dri:div/dri:head" priority="3"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-div-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <!-- The second case is the header on tables, which always creates an HTML h3 element --> - <xsl:template match="dri:table/dri:head" priority="2"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-table-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <!-- The third case is the header on lists, which creates an HTML h3 element for top level lists and - and h4 elements for all sublists. --> - <xsl:template match="dri:list/dri:head" priority="2" mode="nested"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-list-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <xsl:template match="dri:list/dri:list/dri:head" priority="3" mode="nested"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-sublist-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <xsl:template match="dri:referenceSet/dri:head" priority="2"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-list-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <xsl:template match="dri:options/dri:list/dri:head" priority="3"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-option-set-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - - <xsl:template match="dri:head" priority="1"> - <xsl:call-template name="renderHead"> - <xsl:with-param name="class">ds-head</xsl:with-param> - </xsl:call-template> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/forms.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/forms.xsl deleted file mode 100644 index 01faa544858c4538fd4a1fefef052101143f84f9..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/forms.xsl +++ /dev/null @@ -1,312 +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/ - ---> -<!-- - Templates to cover the forms and forms fields. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!--always give the last item the class 'last'--> - <xsl:template match="dri:list[@type='form']/dri:item" priority="3"> - <li> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class"> - <xsl:text>ds-form-item </xsl:text> - <xsl:choose> - <!-- Makes sure that the dark always falls on the last item --> - <xsl:when test="count(../dri:item) mod 2 = 0"> - <xsl:if test="count(../dri:item) > 3"> - <xsl:if test="(count(preceding-sibling::dri:item) mod 2 = 0)">even </xsl:if> - <xsl:if test="(count(preceding-sibling::dri:item) mod 2 = 1)">odd </xsl:if> - </xsl:if> - </xsl:when> - <xsl:when test="count(../dri:item) mod 2 = 1"> - <xsl:if test="count(../dri:item) > 3"> - <xsl:if test="(count(preceding-sibling::dri:item) mod 2 = 1)">even </xsl:if> - <xsl:if test="(count(preceding-sibling::dri:item) mod 2 = 0)">odd </xsl:if> - </xsl:if> - </xsl:when> - </xsl:choose> - <!-- The last row is special--> - <xsl:if test="position()=last()">last </xsl:if> - <!-- The row is also tagged specially if it contains another "form" list --> - <xsl:if test="dri:list[@type='form']">sublist </xsl:if> - </xsl:with-param> - </xsl:call-template> - - <xsl:choose> - <xsl:when test="dri:field[@type='composite']"> - <xsl:call-template name="pick-label"/> - <xsl:apply-templates mode="formComposite"/> - </xsl:when> - <xsl:when test="dri:list[@type='form']"> - <xsl:apply-templates /> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name="pick-label"/> - <div class="ds-form-content"> - <xsl:apply-templates /> - <!-- special name used in submission UI review page --> - <xsl:if test="@n = 'submit-review-field-with-authority'"> - <xsl:call-template name="authorityConfidenceIcon"> - <xsl:with-param name="confidence" select="substring-after(./@rend, 'cf-')"/> - </xsl:call-template> - </xsl:if> - </div> - </xsl:otherwise> - </xsl:choose> - </li> - </xsl:template> - - <!-- NON-instance composite fields (i.e. not repeatable) --> - <xsl:template match="dri:field[@type='composite']" mode="formComposite"> - <div class="ds-form-content"> - <xsl:apply-templates select="dri:help" mode="compositeComponent"/> - <xsl:variable name="confidenceIndicatorID" select="concat(translate(@id,'.','_'),'_confidence_indicator')"/> - <xsl:apply-templates select="dri:field" mode="compositeComponent"/> - <xsl:choose> - <xsl:when test="dri:params/@choicesPresentation = 'suggest'"> - <xsl:message terminate="yes"> - <xsl:text>ERROR: Input field with "suggest" (autocomplete) choice behavior is not implemented for Composite (e.g. "name") fields.</xsl:text> - </xsl:message> - </xsl:when> - <!-- lookup popup includes its own Add button if necessary. --> - <xsl:when test="dri:params/@choicesPresentation = 'lookup'"> - <xsl:call-template name="addLookupButton"> - <xsl:with-param name="isName" select="'true'"/> - <xsl:with-param name="confIndicator" select="$confidenceIndicatorID"/> - </xsl:call-template> - </xsl:when> - </xsl:choose> - <xsl:if test="dri:params/@authorityControlled"> - <xsl:variable name="confValue" select="dri:field/dri:value[@type='authority'][1]/@confidence"/> - <xsl:call-template name="authorityConfidenceIcon"> - <xsl:with-param name="confidence" select="$confValue"/> - <xsl:with-param name="id" select="$confidenceIndicatorID"/> - </xsl:call-template> - <xsl:call-template name="authorityInputFields"> - <xsl:with-param name="name" select="@n"/> - <xsl:with-param name="authValue" select="dri:field/dri:value[@type='authority'][1]/text()"/> - <xsl:with-param name="confValue" select="$confValue"/> - </xsl:call-template> - </xsl:if> - <div class="spacer"> </div> - <xsl:apply-templates select="dri:field/dri:error" mode="compositeComponent"/> - <xsl:apply-templates select="dri:error" mode="compositeComponent"/> - </div> - </xsl:template> - - <!-- The handling of the special case of instanced composite fields under "form" lists --> - <xsl:template match="dri:field[@type='composite'][dri:field/dri:instance | dri:params/@operations]" mode="formComposite" priority="2"> - <xsl:variable name="confidenceIndicatorID" select="concat(translate(@id,'.','_'),'_confidence_indicator')"/> - <div class="ds-form-content"> - <xsl:apply-templates select="dri:help" mode="compositeComponent"/> - <xsl:apply-templates select="dri:field" mode="compositeComponent"/> - <xsl:if test="contains(dri:params/@operations,'add')"> - <!-- Add buttons should be named "submit_[field]_add" so that we can ignore errors from required fields when simply adding new values--> - <input type="submit" value="Add" name="{concat('submit_',@n,'_add')}" class="ds-button-field ds-add-button"> - <!-- Make invisible if we have choice-lookup operation that provides its own Add. --> - <xsl:if test="dri:params/@choicesPresentation = 'lookup'"> - <xsl:attribute name="style"> - <xsl:text>display:none;</xsl:text> - </xsl:attribute> - </xsl:if> - </input> - </xsl:if> - <!-- insert choice mechansim and/or Add button here --> - <xsl:choose> - <xsl:when test="dri:params/@choicesPresentation = 'suggest'"> - <xsl:message terminate="yes"> - <xsl:text>ERROR: Input field with "suggest" (autocomplete) choice behavior is not implemented for Composite (e.g. "name") fields.</xsl:text> - </xsl:message> - </xsl:when> - <!-- lookup popup includes its own Add button if necessary. --> - <xsl:when test="dri:params/@choicesPresentation = 'lookup'"> - <xsl:call-template name="addLookupButton"> - <xsl:with-param name="isName" select="'true'"/> - <xsl:with-param name="confIndicator" select="$confidenceIndicatorID"/> - </xsl:call-template> - </xsl:when> - </xsl:choose> - <!-- place to store authority value --> - <xsl:if test="dri:params/@authorityControlled"> - <xsl:call-template name="authorityConfidenceIcon"> - <xsl:with-param name="confidence" select="dri:value[@type='authority']/@confidence"/> - <xsl:with-param name="id" select="$confidenceIndicatorID"/> - </xsl:call-template> - <xsl:call-template name="authorityInputFields"> - <xsl:with-param name="name" select="@n"/> - <xsl:with-param name="authValue" select="dri:value[@type='authority']/text()"/> - <xsl:with-param name="confValue" select="dri:value[@type='authority']/@confidence"/> - </xsl:call-template> - </xsl:if> - <div class="spacer"> </div> - <xsl:apply-templates select="dri:field/dri:error" mode="compositeComponent"/> - <xsl:apply-templates select="dri:error" mode="compositeComponent"/> - <xsl:if test="dri:instance or dri:field/dri:instance"> - <div class="ds-previous-values"> - <xsl:call-template name="fieldIterator"> - <xsl:with-param name="position">1</xsl:with-param> - </xsl:call-template> - <xsl:if test="contains(dri:params/@operations,'delete') and (dri:instance or dri:field/dri:instance)"> - <!-- Delete buttons should be named "submit_[field]_delete" so that we can ignore errors from required fields when simply removing values--> - <input type="submit" value="Remove selected" name="{concat('submit_',@n,'_delete')}" class="ds-button-field ds-delete-button" /> - </xsl:if> - <xsl:for-each select="dri:field"> - <xsl:apply-templates select="dri:instance" mode="hiddenInterpreter"/> - </xsl:for-each> - </div> - </xsl:if> - </div> - </xsl:template> - - - - <!-- The handling of the field element is more complex. At the moment, the handling of input fields in the - DRI schema is very similar to HTML, utilizing the same controlled vocabulary in most cases. This makes - converting DRI fields to HTML inputs a straightforward, if a bit verbose, task. We are currently - looking at other ways of encoding forms, so this may change in the future. --> - <!-- The simple field case... not part of a complex field and does not contain instance values --> - <xsl:template match="dri:field"> - <xsl:variable name="test" select="not(@type='composite') and ancestor::dri:list[@type='form']"/> - <xsl:if test="$test"> - <xsl:apply-templates select="dri:help" mode="help"/> - </xsl:if> - <xsl:apply-templates select="." mode="normalField"/> - <xsl:if test="contains(dri:params/@operations,'add')"> - <!-- Add buttons should be named "submit_[field]_add" so that we can ignore errors from required fields when simply adding new values--> - <input type="submit" value="Add" name="{concat('submit_',@n,'_add')}" class="ds-button-field ds-add-button"> - <!-- Make invisible if we have choice-lookup popup that provides its own Add. --> - <xsl:if test="dri:params/@choicesPresentation = 'lookup'"> - <xsl:attribute name="style"> - <xsl:text>display:none;</xsl:text> - </xsl:attribute> - </xsl:if> - </input> - </xsl:if> - <xsl:if test="$test"> - <xsl:apply-templates select="dri:error" mode="error"/> - </xsl:if> - <xsl:if test="dri:instance"> - <div class="ds-previous-values"> - <!-- Iterate over the dri:instance elements contained in this field. The instances contain - stored values as either "interpreted", "raw", or "default" values. --> - <xsl:call-template name="simpleFieldIterator"> - <xsl:with-param name="position">1</xsl:with-param> - </xsl:call-template> - <!-- Conclude with a DELETE button if the delete operation is specified. This allows - removing one or more values stored for this field. --> - <xsl:if test="contains(dri:params/@operations,'delete') and dri:instance"> - <!-- Delete buttons should be named "submit_[field]_delete" so that we can ignore errors from required fields when simply removing values--> - <input type="submit" value="Remove selected" name="{concat('submit_',@n,'_delete')}" class="ds-button-field ds-delete-button" /> - </xsl:if> - <!-- Behind the scenes, add hidden fields for every instance set. This is to make sure that - the form still submits the information in those instances, even though they are no - longer encoded as HTML fields. The DRI Reference should contain the exact attributes - the hidden fields should have in order for this to work properly. --> - <xsl:apply-templates select="dri:instance" mode="hiddenInterpreter"/> - </div> - </xsl:if> - </xsl:template> - - <!--modified to differentiate beween selects with and without attribute 'multiple'--> - <xsl:template name="fieldAttributes"> - <xsl:call-template name="standardAttributes"> - <xsl:with-param name="class"> - <xsl:text>ds-</xsl:text><xsl:value-of select="@type"/> - <xsl:text>-field </xsl:text> - <xsl:if test="@disabled='yes'"> - <xsl:text>disabled </xsl:text> - </xsl:if> - <xsl:if test="dri:error or parent::node()[@type='composite']/dri:error"> - <xsl:text>error </xsl:text> - </xsl:if> - <xsl:if test="dri:params/@multiple='yes'"> - <xsl:text>multiple </xsl:text> - </xsl:if> - </xsl:with-param> - </xsl:call-template> - <xsl:if test="@disabled='yes'"> - <xsl:attribute name="disabled">disabled</xsl:attribute> - </xsl:if> - <xsl:if test="@type != 'checkbox' and @type != 'radio' "> - <xsl:attribute name="name"><xsl:value-of select="@n"/></xsl:attribute> - </xsl:if> - <xsl:if test="@type != 'select' and @type != 'textarea' and @type != 'checkbox' and @type != 'radio' "> - <xsl:attribute name="type"><xsl:value-of select="@type"/></xsl:attribute> - </xsl:if> - <xsl:if test="@type= 'textarea'"> - <xsl:attribute name="onfocus">javascript:tFocus(this);</xsl:attribute> - </xsl:if> - </xsl:template> - - - <!-- Fieldset (instanced) field stuff, in the case of non-composites --> - <xsl:template match="dri:field[dri:field/dri:instance | dri:params/@operations]" priority="2"> - <xsl:apply-templates select="dri:help" mode="help"/> - <!-- Create the first field normally --> - <xsl:apply-templates select="." mode="normalField"/> - <!-- Follow it up with an ADD button if the add operation is specified. This allows - entering more than one value for this field. --> - <xsl:if test="contains(dri:params/@operations,'add')"> - <!-- Add buttons should be named "submit_[field]_add" so that we can ignore errors from required fields when simply adding new values--> - <input type="submit" value="Add" name="{concat('submit_',@n,'_add')}" class="ds-button-field ds-add-button"> - <!-- Make invisible if we have choice-lookup popup that provides its own Add. --> - <xsl:if test="dri:params/@choicesPresentation = 'lookup'"> - <xsl:attribute name="style"> - <xsl:text>display:none;</xsl:text> - </xsl:attribute> - </xsl:if> - </input> - </xsl:if> - <br/> - <xsl:apply-templates select="dri:error" mode="error"/> - <xsl:if test="dri:instance"> - <div class="ds-previous-values"> - <!-- Iterate over the dri:instance elements contained in this field. The instances contain - stored values as either "interpreted", "raw", or "default" values. --> - <xsl:call-template name="simpleFieldIterator"> - <xsl:with-param name="position">1</xsl:with-param> - </xsl:call-template> - <!-- Conclude with a DELETE button if the delete operation is specified. This allows - removing one or more values stored for this field. --> - <xsl:if test="contains(dri:params/@operations,'delete') and dri:instance"> - <!-- Delete buttons should be named "submit_[field]_delete" so that we can ignore errors from required fields when simply removing values--> - <input type="submit" value="Remove selected" name="{concat('submit_',@n,'_delete')}" class="ds-button-field ds-delete-button" /> - </xsl:if> - <!-- Behind the scenes, add hidden fields for every instance set. This is to make sure that - the form still submits the information in those instances, even though they are no - longer encoded as HTML fields. The DRI Reference should contain the exact attributes - the hidden fields should have in order for this to work properly. --> - <xsl:apply-templates select="dri:instance" mode="hiddenInterpreter"/> - </div> - </xsl:if> - </xsl:template> - - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/global-variables.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/global-variables.xsl deleted file mode 100644 index 211f593e955262198d5853ece55814dfb7557898..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/global-variables.xsl +++ /dev/null @@ -1,42 +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/ - ---> -<!-- - Global variables accessible from other templates - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - xmlns:confman="org.dspace.core.ConfigurationManager" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc confman"> - - <xsl:output indent="yes"/> - - <!--the max thumbnail height & width from dspace.cfg, needed for item view and item list pages--> - <xsl:variable name="thumbnail.maxheight" select="confman:getIntProperty('thumbnail.maxheight', 80)"/> - <xsl:variable name="thumbnail.maxwidth" select="confman:getIntProperty('thumbnail.maxwidth', 80)"/> - <!-- item details url --> - <xsl:variable name="ds_item_view_toggle_url" select="//dri:p[contains(@rend , 'item-view-toggle') and - (preceding-sibling::dri:referenceSet[@type = 'summaryView'] or following-sibling::dri:referenceSet[@type = 'summaryView'])]/dri:xref/@target"/> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/navigation.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/navigation.xsl deleted file mode 100644 index 6f58714bab2bab3c0024cdbab81f667d770ff764..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/navigation.xsl +++ /dev/null @@ -1,200 +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/ - ---> -<!-- - Rendering specific to the navigation (options) - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!-- - The template to handle dri:options. Since it contains only dri:list tags (which carry the actual - information), the only things than need to be done is creating the ds-options div and applying - the templates inside it. - - In fact, the only bit of real work this template does is add the search box, which has to be - handled specially in that it is not actually included in the options div, and is instead built - from metadata available under pageMeta. - --> - <!-- TODO: figure out why i18n tags break the go button --> - <xsl:template match="dri:options"> - <div id="ds-options-wrapper"> - <div id="ds-options"> - <xsl:if test="not(contains(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='URI'], 'discover'))"> - <h1 id="ds-search-option-head" class="ds-option-set-head"> - <i18n:text>xmlui.dri2xhtml.structural.search</i18n:text> - </h1> - <div id="ds-search-option" class="ds-option-set"> - <!-- The form, complete with a text box and a button, all built from attributes referenced - from under pageMeta. --> - <form id="ds-search-form" method="post"> - <xsl:attribute name="action"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath']"/> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='simpleURL']"/> - </xsl:attribute> - <fieldset> - <input class="ds-text-field " type="text"> - <xsl:attribute name="name"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='queryField']"/> - </xsl:attribute> - </input> - <input class="ds-button-field " name="submit" type="submit" i18n:attr="value" - value="xmlui.general.go"> - <xsl:attribute name="onclick"> - <xsl:text> - var radio = document.getElementById("ds-search-form-scope-container"); - if (radio != undefined && radio.checked) - { - var form = document.getElementById("ds-search-form"); - form.action= - </xsl:text> - <xsl:text>"</xsl:text> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath']"/> - <xsl:text>/handle/" + radio.value + "</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='simpleURL']"/> - <xsl:text>" ; </xsl:text> - <xsl:text> - } - </xsl:text> - </xsl:attribute> - </input> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='focus'][@qualifier='container']"> - <label> - <input id="ds-search-form-scope-all" type="radio" name="scope" value="" - checked="checked"/> - <i18n:text>xmlui.dri2xhtml.structural.search</i18n:text> - </label> - <br/> - <label> - <input id="ds-search-form-scope-container" type="radio" name="scope"> - <xsl:attribute name="value"> - <xsl:value-of - select="substring-after(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='focus'][@qualifier='container'],':')"/> - </xsl:attribute> - </input> - <xsl:choose> - <xsl:when - test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='focus'][@qualifier='containerType']/text() = 'type:community'"> - <i18n:text>xmlui.dri2xhtml.structural.search-in-community</i18n:text> - </xsl:when> - <xsl:otherwise> - <i18n:text>xmlui.dri2xhtml.structural.search-in-collection</i18n:text> - </xsl:otherwise> - - </xsl:choose> - </label> - </xsl:if> - </fieldset> - </form> - <!--Only add if the advanced search url is different from the simple search--> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='advancedURL'] != /dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='simpleURL']"> - <!-- The "Advanced search" link, to be perched underneath the search box --> - <a> - <xsl:attribute name="href"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search'][@qualifier='advancedURL']"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.search-advanced</i18n:text> - </a> - </xsl:if> - </div> - - </xsl:if> - <!-- Once the search box is built, the other parts of the options are added --> - <xsl:apply-templates/> - - <!-- DS-984 Add RSS Links to Options Box --> - <xsl:if test="count(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='feed']) != 0"> - <h1 id="ds-feed-option-head" class="ds-option-set-head"> - <i18n:text>xmlui.feed.header</i18n:text> - </h1> - <div id="ds-feed-option" class="ds-option-set"> - <ul> - <xsl:call-template name="addRSSLinks"/> - </ul> - </div> - </xsl:if> - - - </div> - </div> - </xsl:template> - - <!-- Add each RSS feed from meta to a list --> - <xsl:template name="addRSSLinks"> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='feed']"> - <li> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="."/> - </xsl:attribute> - - <xsl:attribute name="style"> - <xsl:text>background: url(</xsl:text> - <xsl:value-of select="$context-path"/> - <xsl:text>/static/icons/feed.png) no-repeat</xsl:text> - </xsl:attribute> - - <xsl:choose> - <xsl:when test="contains(., 'rss_1.0')"> - <xsl:text>RSS 1.0</xsl:text> - </xsl:when> - <xsl:when test="contains(., 'rss_2.0')"> - <xsl:text>RSS 2.0</xsl:text> - </xsl:when> - <xsl:when test="contains(., 'atom_1.0')"> - <xsl:text>Atom</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select="@qualifier"/> - </xsl:otherwise> - </xsl:choose> - </a> - </li> - </xsl:for-each> - </xsl:template> - - <!--give nested navigation list the class sublist--> - <xsl:template match="dri:options/dri:list/dri:list" priority="3" mode="nested"> - <li> - <xsl:apply-templates select="dri:head" mode="nested"/> - <ul class="ds-simple-list sublist"> - <xsl:apply-templates select="dri:item" mode="nested"/> - </ul> - </li> - </xsl:template> - - <!-- Quick patch to remove empty lists from options --> - <xsl:template match="dri:options//dri:list[count(child::*)=0]" priority="5" mode="nested"> - </xsl:template> - <xsl:template match="dri:options//dri:list[count(child::*)=0]" priority="5"> - </xsl:template> - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/page-structure.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/page-structure.xsl deleted file mode 100644 index 83e01ed6a6f836682877cbf48f0660eb05863ff9..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/page-structure.xsl +++ /dev/null @@ -1,929 +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/ - ---> -<!-- - Main structure of the page, determines where - header, footer, body, navigation are structurally rendered. - Rendering of the header, footer, trail and alerts - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:confman="org.dspace.core.ConfigurationManager" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc confman"> - - <xsl:output indent="yes"/> - - <!-- - 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. - --> - <xsl:variable name="request-uri" select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='URI']"/> - - <!-- - The starting point of any XSL processing is matching the root element. In DRI the root element is document, - which contains a version attribute and three top level elements: body, options, meta (in that order). - - This template creates the html document, giving it a head and body. A title and the CSS style reference - are placed in the html head, while the body is further split into several divs. The top-level div - directly under html body is called "ds-main". It is further subdivided into: - "ds-header" - the header div containing title, subtitle, trail and other front matter - "ds-body" - the div containing all the content of the page; built from the contents of dri:body - "ds-options" - the div with all the navigation and actions; built from the contents of dri:options - "ds-footer" - optional footer div, containing misc information - - The order in which the top level divisions appear may have some impact on the design of CSS and the - final appearance of the DSpace page. While the layout of the DRI schema does favor the above div - arrangement, nothing is preventing the designer from changing them around or adding new ones by - overriding the dri:document template. - --> - <xsl:template match="dri:document"> - <html class="no-js"> - <!-- First of all, build the HTML head element --> - <xsl:call-template name="buildHead"/> - <!-- Then proceed to the body --> - - <!--paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/--> - <xsl:text disable-output-escaping="yes"><!--[if lt IE 7 ]> <body class="ie6"> <![endif]--> - <!--[if IE 7 ]> <body class="ie7"> <![endif]--> - <!--[if IE 8 ]> <body class="ie8"> <![endif]--> - <!--[if IE 9 ]> <body class="ie9"> <![endif]--> - <!--[if (gt IE 9)|!(IE)]><!--><body><!--<![endif]--></xsl:text> - - <xsl:choose> - <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='framing'][@qualifier='popup']"> - <xsl:apply-templates select="dri:body/*"/> - </xsl:when> - <xsl:otherwise> - <div id="ds-main"> - <!-- Barra Brasil --> - <xsl:call-template name="buildBarra" /> - - <!--The header div, complete with title, subtitle and other junk--> - <xsl:call-template name="buildHeader"/> - - <!--The trail is built by applying a template over pageMeta's trail children. --> - <xsl:call-template name="buildTrail"/> - - <!--javascript-disabled warning, will be invisible if javascript is enabled--> - <div id="no-js-warning-wrapper" class="hidden"> - <div id="no-js-warning"> - <div class="notice failure"> - <xsl:text>JavaScript is disabled for your browser. Some features of this site may not work without it.</xsl:text> - </div> - </div> - </div> - - - <!--ds-content is a groups ds-body and the navigation together and used to put the clearfix on, center, etc. - ds-content-wrapper is necessary for IE6 to allow it to center the page content--> - <div id="ds-content-wrapper"> - <div id="ds-content" class="clearfix"> - <!-- - 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 - the ds-options div that contains the navigation and action options available to the - user. The meta element is ignored since its contents are not processed directly, but - instead referenced from the different points in the document. --> - <xsl:apply-templates/> - </div> - </div> - - - <!-- - The footer div, dropping whatever extra information is needed on the page. It will - most likely be something similar in structure to the currently given example. --> - <xsl:call-template name="buildFooter"/> - - </div> - - </xsl:otherwise> - </xsl:choose> - <!-- Javascript at the bottom for fast page loading --> - <xsl:call-template name="addJavascript"/> - - <xsl:text disable-output-escaping="yes"></body></xsl:text> - </html> - </xsl:template> - - <!-- The HTML head element contains references to CSS as well as embedded JavaScript code. Most of this - information is either user-provided bits of post-processing (as in the case of the JavaScript), or - references to stylesheets pulled directly from the pageMeta element. --> - <xsl:template name="buildHead"> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> - - <!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame --> - <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/> - - <!-- Mobile Viewport Fix - j.mp/mobileviewport & davidbcalhoun.com/2010/viewport-metatag - device-width : Occupy full width of the screen in its current orientation - initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height - maximum-scale = 1.0 retains dimensions instead of zooming in if page width < device width - --> - <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0;"/> - - <link rel="shortcut icon"> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/images/favicon.ico</xsl:text> - </xsl:attribute> - </link> - <link rel="apple-touch-icon"> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/images/apple-touch-icon.png</xsl:text> - </xsl:attribute> - </link> - - <meta name="Generator"> - <xsl:attribute name="content"> - <xsl:text>DSpace</xsl:text> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='dspace'][@qualifier='version']"> - <xsl:text> </xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='dspace'][@qualifier='version']"/> - </xsl:if> - </xsl:attribute> - </meta> - <!-- Add stylsheets --> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='stylesheet']"> - <link rel="stylesheet" type="text/css"> - <xsl:attribute name="media"> - <xsl:value-of select="@qualifier"/> - </xsl:attribute> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/</xsl:text> - <xsl:value-of select="."/> - </xsl:attribute> - </link> - </xsl:for-each> - - <!-- Add syndication feeds --> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='feed']"> - <link rel="alternate" type="application"> - <xsl:attribute name="type"> - <xsl:text>application/</xsl:text> - <xsl:value-of select="@qualifier"/> - </xsl:attribute> - <xsl:attribute name="href"> - <xsl:value-of select="."/> - </xsl:attribute> - </link> - </xsl:for-each> - - <!-- Add OpenSearch auto-discovery link --> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='opensearch'][@qualifier='shortName']"> - <link rel="search" type="application/opensearchdescription+xml"> - <xsl:attribute name="href"> - <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="$context-path"/> - <xsl:text>/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='opensearch'][@qualifier='autolink']"/> - </xsl:attribute> - <xsl:attribute name="title" > - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='opensearch'][@qualifier='shortName']"/> - </xsl:attribute> - </link> - </xsl:if> - - <!-- The following javascript removes the default text of empty text areas when they are focused on or submitted --> - <!-- There is also javascript to disable submitting a form when the 'enter' key is pressed. --> - <script type="text/javascript"> - //Clear default text of empty text areas on focus - function tFocus(element) - { - if (element.value == '<i18n:text>xmlui.dri2xhtml.default.textarea.value</i18n:text>'){element.value='';} - } - //Clear default text of empty text areas on submit - function tSubmit(form) - { - var defaultedElements = document.getElementsByTagName("textarea"); - for (var i=0; i != defaultedElements.length; i++){ - if (defaultedElements[i].value == '<i18n:text>xmlui.dri2xhtml.default.textarea.value</i18n:text>'){ - defaultedElements[i].value='';}} - } - //Disable pressing 'enter' key to submit a form (otherwise pressing 'enter' causes a submission to start over) - function disableEnterKey(e) - { - var key; - - if(window.event) - key = window.event.keyCode; //Internet Explorer - else - key = e.which; //Firefox and Netscape - - if(key == 13) //if "Enter" pressed, then disable! - return false; - else - return true; - } - - function FnArray() - { - this.funcs = new Array; - } - - FnArray.prototype.add = function(f) - { - if( typeof f!= "function" ) - { - f = new Function(f); - } - this.funcs[this.funcs.length] = f; - }; - - FnArray.prototype.execute = function() - { - for( var i=0; i <xsl:text disable-output-escaping="yes"><</xsl:text> this.funcs.length; i++ ) - { - this.funcs[i](); - } - }; - - var runAfterJSImports = new FnArray(); - </script> - - <!-- Modernizr enables HTML5 elements & feature detects --> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/lib/js/modernizr-1.7.min.js</xsl:text> - </xsl:attribute> </script> - - <!-- Add the title in --> - <xsl:variable name="page_title" select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title']" /> - <title> - <xsl:choose> - <xsl:when test="starts-with($request-uri, 'page/about')"> - <i18n:text>xmlui.structure.AboutRepositoryTitle</i18n:text> - </xsl:when> - <xsl:when test="not($page_title)"> - <xsl:text> </xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:copy-of select="$page_title/node()" /> - </xsl:otherwise> - </xsl:choose> - </title> - - <!-- Head metadata in item pages --> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='xhtml_head_item']"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='xhtml_head_item']" - disable-output-escaping="yes"/> - </xsl:if> - - <!-- Add all Google Scholar Metadata values --> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[substring(@element, 1, 9) = 'citation_']"> - <meta name="{@element}" content="{.}"></meta> - </xsl:for-each> - - </head> - </xsl:template> - - - <xsl:template name="buildBarra"> - <div id="barra-brasil"> - <div class="barra"> - <ul> - <li> - <a id="ds-header-logo-link" - href="http://www.acessoainformacao.gov.br" > - <span id="barra-brasil-ai"> </span> - </a> - </li> - <li> - <a id="ds-header-logo-link" - href="http://www.brasil.gov.br" > - <span id="barra-brasil-brasilgov"> </span> - </a> - </li> - </ul> - </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="buildHeader"> - - <div id="ds-header-wrapper"> - <div id="ds-header" class="clearfix"> - <a id="ds-header-logo-link"> - <xsl:attribute name="href"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/</xsl:text> - </xsl:attribute> - <span id="ds-header-logo"> </span> - <!-- <span id="ds-header-logo-text">mirage</span> --> - </a> - <h1 class="pagetitle visuallyhidden"> - <xsl:choose> - <!-- protection against an empty page title --> - <xsl:when test="not(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title'])"> - <xsl:text> </xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:copy-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title']/node()"/> - </xsl:otherwise> - </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'"> - <div id="ds-user-box"> - <p> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:userMeta/ - dri:metadata[@element='identifier' and @qualifier='url']"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.profile</i18n:text> - <xsl:value-of select="/dri:document/dri:meta/dri:userMeta/ - dri:metadata[@element='identifier' and @qualifier='firstName']"/> - <xsl:text> </xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:userMeta/ - dri:metadata[@element='identifier' and @qualifier='lastName']"/> - </a> - <xsl:text> | </xsl:text> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:userMeta/ - dri:metadata[@element='identifier' and @qualifier='logoutURL']"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.logout</i18n:text> - </a> - </p> - </div> - </xsl:when> - <xsl:otherwise> - <div id="ds-user-box"> - <p> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="/dri:document/dri:meta/dri:userMeta/ - dri:metadata[@element='identifier' and @qualifier='loginURL']"/> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.login</i18n:text> - </a> - </p> - </div> - </xsl:otherwise> - </xsl:choose> - - </div> - </div> - </xsl:template> - - - <!-- Trail... --> - <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:template name="cc-license"> - <xsl:param name="metadataURL"/> - <xsl:variable name="externalMetadataURL"> - <xsl:text>cocoon:/</xsl:text> - <xsl:value-of select="$metadataURL"/> - <xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL</xsl:text> - </xsl:variable> - - <xsl:variable name="ccLicenseName" - select="document($externalMetadataURL)//dim:field[@element='rights']" - /> - <xsl:variable name="ccLicenseUri" - select="document($externalMetadataURL)//dim:field[@element='rights'][@qualifier='uri']" - /> - <xsl:variable name="handleUri"> - <xsl:for-each select="document($externalMetadataURL)//dim:field[@element='identifier' and @qualifier='uri']"> - <a> - <xsl:attribute name="href"> - <xsl:copy-of select="./node()"/> - </xsl:attribute> - <xsl:copy-of select="./node()"/> - </a> - <xsl:if test="count(following-sibling::dim:field[@element='identifier' and @qualifier='uri']) != 0"> - <xsl:text>, </xsl:text> - </xsl:if> - </xsl:for-each> - </xsl:variable> - - <xsl:if test="$ccLicenseName and $ccLicenseUri and contains($ccLicenseUri, 'creativecommons')"> - <div about="{$handleUri}" class="clearfix"> - <xsl:attribute name="style"> - <xsl:text>margin:0em 2em 0em 2em; padding-bottom:0em;</xsl:text> - </xsl:attribute> - <a rel="license" - href="{$ccLicenseUri}" - 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> - </a> - <span> - <xsl:attribute name="style"> - <xsl:text>vertical-align:middle; text-indent:0 !important;</xsl:text> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.METS-1.0.cc-license-text</i18n:text> - <xsl:value-of select="$ccLicenseName"/> - </span> - </div> - </xsl:if> - </xsl:template> - - - <!-- Like the header, the footer contains various miscellaneous text, links, and image placeholders --> - <xsl:template name="buildFooter"> - <div id="ds-footer-wrapper"> - <div id="ds-footer"> - <div> - <img id="ds-footer-banner" usemap="#banner-map"/> - <map id="banner-map" name="banner-map"> - <area shape="rect" alt="Universidade Federal do Rio de Janeiro" title="Universidade Federal do Rio de Janeiro" coords="17,40,170,83" href="http://www.ufrj.br/" target="_blank"/> - <area shape="rect" alt="Universidade Federal do Paraná" title="Universidade Federal do Paraná" coords="204,28,298,93" href="http://www.ufpr.br/" target="_blank"/> - <area shape="rect" alt="Secretaria Nacional de Juventude" title="Secretaria Nacional de Juventude" coords="417,43,544,86" href="http://www.juventude.gov.br/" target="_blank"/> - <area shape="rect" alt="Secretaria-Geral da Presidência da República" title="Secretaria-Geral da Presidência da República" coords="563,44,742,88" href="http://www.secretariageral.gov.br/" target="_blank"/> - <area shape="rect" alt="Portal Brasil" title="Portal Brasil" coords="763,28,968,98" href="http://www.brasil.gov.br/" target="_blank"/> - </map> - </div> - <div id="ds-footer-powered"> - <ul> - <li> - <a id="ds-footer-logo-link" href="http://www.c3sl.ufpr.br" > - <span id="ds-footer-c3sl"> </span> - </a> - </li> - <li> - <a id="ds-footer-logo-link" href="http://www.dspace.org/"> - <span id="ds-footer-dspace"> </span> - </a> - </li> - </ul> - </div> -<!-- Original: - <div id="ds-footer-left"> - <a href="http://www.dspace.org/" target="_blank">DSpace software</a> copyright © 2002-2012  <a href="http://www.duraspace.org/" target="_blank">Duraspace</a> - </div> - <div id="ds-footer-right"> - <span class="theme-by">Theme by </span> - <a title="@mire NV" target="_blank" href="http://atmire.com" id="ds-footer-logo-link"> - <span id="ds-footer-logo"> </span> - </a> - </div> - <div id="ds-footer-links"> - <a> - <xsl:attribute name="href"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/contact</xsl:text> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.contact-link</i18n:text> - </a> - <xsl:text> | </xsl:text> - <a> - <xsl:attribute name="href"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/feedback</xsl:text> - </xsl:attribute> - <i18n:text>xmlui.dri2xhtml.structural.feedback-link</i18n:text> - </a> - </div> ---> - <!--Invisible link to HTML sitemap (for search engines) --> - <a class="hidden"> - <xsl:attribute name="href"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/htmlmap</xsl:text> - </xsl:attribute> - <xsl:text> </xsl:text> - </a> - </div> - </div> - </xsl:template> - - -<!-- - The meta, body, options elements; the three top-level elements in the schema ---> - - - - - <!-- - The template to handle the dri:body element. It simply creates the ds-body div and applies - templates of the body's child elements (which consists entirely of dri:div tags). - --> - <xsl:template match="dri:body"> - <div id="ds-body"> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='alert'][@qualifier='message']"> - <div id="ds-system-wide-alert"> - <p> - <xsl:copy-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='alert'][@qualifier='message']/node()"/> - </p> - </div> - </xsl:if> - - <!-- Check for the custom pages --> - <xsl:choose> - <xsl:when test="starts-with($request-uri, 'page/about')"> - <div> - <h1><i18n:text>xmlui.structure.AboutRepositoryTitle</i18n:text></h1> - <p><i18n:text>xmlui.structure.AboutRepositoryText</i18n:text></p> - </div> - </xsl:when> - -<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> -<!-- <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title']/i18n:text='xmlui.general.dspace_home'"> --> <!-- Se for a homepage --> - <xsl:when test="starts-with($request-uri, 'page/teste')"> - <xsl:call-template name="staticHomePage"/> <!-- Implementado no fim deste arquivo --> - </xsl:when> -<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> - - <!-- Otherwise use default handling of body --> - <xsl:otherwise> - <xsl:apply-templates /> - </xsl:otherwise> - </xsl:choose> - - </div> - </xsl:template> - - - <!-- Currently the dri:meta element is not parsed directly. Instead, parts of it are referenced from inside - other elements (like reference). The blank template below ends the execution of the meta branch --> - <xsl:template match="dri:meta"> - </xsl:template> - - <!-- Meta's children: userMeta, pageMeta, objectMeta and repositoryMeta may or may not have templates of - their own. This depends on the meta template implementation, which currently does not go this deep. - <xsl:template match="dri:userMeta" /> - <xsl:template match="dri:pageMeta" /> - <xsl:template match="dri:objectMeta" /> - <xsl:template match="dri:repositoryMeta" /> - --> - - <xsl:template name="addJavascript"> - <xsl:variable name="jqueryVersion"> - <xsl:text>1.6.2</xsl:text> - </xsl:variable> - - <xsl:variable name="protocol"> - <xsl:choose> - <xsl:when test="starts-with(confman:getProperty('dspace.baseUrl'), 'https://')"> - <xsl:text>https://</xsl:text> - </xsl:when> - <xsl:otherwise> - <xsl:text>http://</xsl:text> - </xsl:otherwise> - </xsl:choose> - </xsl:variable> - <script type="text/javascript" src="{concat($protocol, 'ajax.googleapis.com/ajax/libs/jquery/', $jqueryVersion ,'/jquery.min.js')}"> </script> - - <xsl:variable name="localJQuerySrc"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/static/js/jquery-</xsl:text> - <xsl:value-of select="$jqueryVersion"/> - <xsl:text>.min.js</xsl:text> - </xsl:variable> - - <script type="text/javascript"> - <xsl:text disable-output-escaping="yes">!window.jQuery && document.write('<script type="text/javascript" src="</xsl:text><xsl:value-of - select="$localJQuerySrc"/><xsl:text disable-output-escaping="yes">"> <\/script>')</xsl:text> - </script> - - - - <!-- Add theme javascipt --> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='javascript'][@qualifier='url']"> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of select="."/> - </xsl:attribute> </script> - </xsl:for-each> - - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='javascript'][not(@qualifier)]"> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/</xsl:text> - <xsl:value-of select="."/> - </xsl:attribute> </script> - </xsl:for-each> - - <!-- add "shared" javascript from static, path is relative to webapp root --> - <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='javascript'][@qualifier='static']"> - <!--This is a dirty way of keeping the scriptaculous stuff from choice-support - out of our theme without modifying the administrative and submission sitemaps. - This is obviously not ideal, but adding those scripts in those sitemaps is far - from ideal as well--> - <xsl:choose> - <xsl:when test="text() = 'static/js/choice-support.js'"> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/lib/js/choice-support.js</xsl:text> - </xsl:attribute> </script> - </xsl:when> - <xsl:when test="not(starts-with(text(), 'static/js/scriptaculous'))"> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/</xsl:text> - <xsl:value-of select="."/> - </xsl:attribute> </script> - </xsl:when> - </xsl:choose> - </xsl:for-each> - - <!-- add setup JS code if this is a choices lookup page --> - <xsl:if test="dri:body/dri:div[@n='lookup']"> - <xsl:call-template name="choiceLookupPopUpSetup"/> - </xsl:if> - - <!--PNG Fix for IE6--> - <xsl:text disable-output-escaping="yes"><!--[if lt IE 7 ]></xsl:text> - <script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'][not(@qualifier)]"/> - <xsl:text>/themes/</xsl:text> - <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path']"/> - <xsl:text>/lib/js/DD_belatedPNG_0.0.8a.js?v=1</xsl:text> - </xsl:attribute> </script> - <script type="text/javascript"> - <xsl:text>DD_belatedPNG.fix('#ds-header-logo');DD_belatedPNG.fix('#ds-footer-logo');$.each($('img[src$=png]'), function() {DD_belatedPNG.fixPng(this);});</xsl:text> - </script> - <xsl:text disable-output-escaping="yes" ><![endif]--></xsl:text> - - - <script type="text/javascript"> - runAfterJSImports.execute(); - </script> - - <!-- Add a google analytics script if the key is present --> - <xsl:if test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='google'][@qualifier='analytics']"> - <script type="text/javascript"><xsl:text> - var _gaq = _gaq || []; - _gaq.push(['_setAccount', '</xsl:text><xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='google'][@qualifier='analytics']"/><xsl:text>']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - </xsl:text></script> - </xsl:if> - </xsl:template> - - - - - - <!--Constrói a HomePage --> - <xsl:template name="staticHomePage"> - <!-- Search --> - <h1 class="ds-div-head"> - <i18n:text>xmlui.structure.AboutRepositoryTitle</i18n:text> - </h1> - <form xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - id="aspect_discovery_SiteViewer_div_front-page-search" class="ds-interactive-div primary" - action="/xmlui/discover" method="get" onsubmit="javascript:tSubmit(this);"> - <p class="ds-paragraph"> - <i18n:text>xmlui.ArtifactBrowser.FrontPageSearch.para1</i18n:text> - </p> - <p xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - class="ds-paragraph"> - <input id="aspect_discovery_SiteViewer_field_query" class="ds-text-field" - name="query" value="" type="text" /> - - <input xmlns:i18n="http://apache.org/cocoon/i18n/2.1" id="aspect_discovery_SiteViewer_field_submit" - class="ds-button-field" name="submit" i18n:attr="value" value="xmlui.general.go" - type="submit" /> - </p> - </form> - - <!-- Community Browser --> - <h1 xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - class="ds-div-head"> - <i18n:text>xmlui.ArtifactBrowser.CommunityBrowser.head</i18n:text> - </h1> - <div xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - id="aspect_artifactbrowser_CommunityBrowser_div_comunity-browser" - class="ds-static-div primary"> - <p class="ds-paragraph"> - <i18n:text>xmlui.ArtifactBrowser.CommunityBrowser.select</i18n:text> - </p> - <ul xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - xmlns:oreatom="http://www.openarchives.org/ore/atom/" xmlns:ore="http://www.openarchives.org/ore/terms/" - xmlns:atom="http://www.w3.org/2005/Atom"> - <!-- External Metadata URL: cocoon://metadata/handle/123456789/13/mets.xml?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL --> - <li class="ds-artifact-item community odd"> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="/xmlui/handle/123456789/13"> - <span class="Z3988">Acervo Geral (AG)</span> - </a> - </div> - </div> - </li> - <!-- External Metadata URL: cocoon://metadata/handle/123456789/11/mets.xml?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL --> - <li class="ds-artifact-item community even"> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="/xmlui/handle/123456789/11"> - <span class="Z3988">Conselho Nacional de Juventude (CONJUVE) - </span> - </a> - </div> - </div> - </li> - <!-- External Metadata URL: cocoon://metadata/handle/123456789/12/mets.xml?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL --> - <li class="ds-artifact-item community odd"> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="/xmlui/handle/123456789/12"> - <span class="Z3988">Organização Ibero-Americana de Juventude (OIJ) - </span> - </a> - </div> - </div> - </li> - <!-- External Metadata URL: cocoon://metadata/handle/123456789/8/mets.xml?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL --> - <li class="ds-artifact-item community even"> - <div class="artifact-description"> - <div class="artifact-title"> - <a href="/xmlui/handle/123456789/8"> - <span class="Z3988">Secretaria Nacional de Juventude (SNJ)</span> - </a> - </div> - <div class="artifact-info"> - <span class="short-description">Comunidade da Secretaria Nacional de Juventude - (SNJ) - </span> - </div> - </div> - </li> - </ul> - </div> - - <!-- News.xml --> - <h1 class="ds-div-head"> - <i18n:text>participatorio.repo.title</i18n:text> - </h1> - <div xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - id="file_news_div_news" class="ds-static-div primary"> - <p class="ds-paragraph"> - <i18n:text>participatorio.repo.text</i18n:text> - </p> - </div> - <h1 xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - class="ds-div-head"> - <i18n:text>participatorio.repo.titleMissao</i18n:text> - </h1> - <div xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - id="file_news_div_news" class="ds-static-div primary"> - <p class="ds-paragraph"> - <i18n:text>participatorio.repo.textMissao</i18n:text> - </p> - </div> - <h1 xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - class="ds-div-head"> - <i18n:text>participatorio.repo.titleObjetivo</i18n:text> - </h1> - <div xmlns:i18n="http://apache.org/cocoon/i18n/2.1" xmlns="http://di.tamu.edu/DRI/1.0/" - id="file_news_div_news" class="ds-static-div primary"> - <p class="ds-paragraph"> - <i18n:text>participatorio.repo.textObjetivo</i18n:text> - </p> - </div> - </xsl:template> - - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/utils.xsl b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/utils.xsl deleted file mode 100644 index 97d54206e5b7af91eec2cf4fe8406164a3cb16ad..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/lib/xsl/core/utils.xsl +++ /dev/null @@ -1,69 +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 stylesheet contains helper templates for things like i18n and standard attributes. - - Author: art.lowel at atmire.com - Author: lieven.droogmans at atmire.com - Author: ben at atmire.com - Author: Alexey Maslov - ---> - -<xsl:stylesheet xmlns:i18n="http://apache.org/cocoon/i18n/2.1" - xmlns:dri="http://di.tamu.edu/DRI/1.0/" - xmlns:mets="http://www.loc.gov/METS/" - xmlns:xlink="http://www.w3.org/TR/xlink/" - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" - xmlns:dim="http://www.dspace.org/xmlns/dspace/dim" - xmlns:xhtml="http://www.w3.org/1999/xhtml" - xmlns:mods="http://www.loc.gov/mods/v3" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns="http://www.w3.org/1999/xhtml" - exclude-result-prefixes="i18n dri mets xlink xsl dim xhtml mods dc"> - - <xsl:output indent="yes"/> - - <!--added classes to differentiate between collections, communities and items--> - <xsl:template match="dri:reference" mode="summaryList"> - <xsl:variable name="externalMetadataURL"> - <xsl:text>cocoon:/</xsl:text> - <xsl:value-of select="@url"/> - <!-- Since this is a summary only grab the descriptive metadata, and the thumbnails --> - <xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=THUMBNAIL</xsl:text> - <!-- An example of requesting a specific metadata standard (MODS and QDC crosswalks only work for items)-> - <xsl:if test="@type='DSpace Item'"> - <xsl:text>&dmdTypes=DC</xsl:text> - </xsl:if>--> - </xsl:variable> - <xsl:comment> External Metadata URL: <xsl:value-of select="$externalMetadataURL"/> </xsl:comment> - <li> - <xsl:attribute name="class"> - <xsl:text>ds-artifact-item </xsl:text> - <xsl:choose> - <xsl:when test="contains(@type, 'Community')"> - <xsl:text>community </xsl:text> - </xsl:when> - <xsl:when test="contains(@type, 'Collection')"> - <xsl:text>collection </xsl:text> - </xsl:when> - </xsl:choose> - <xsl:choose> - <xsl:when test="position() mod 2 = 0">even</xsl:when> - <xsl:otherwise>odd</xsl:otherwise> - </xsl:choose> - </xsl:attribute> - <xsl:apply-templates select="document($externalMetadataURL)" mode="summaryList"/> - <xsl:apply-templates /> - </li> - </xsl:template> - - -</xsl:stylesheet> diff --git a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/sitemap.xmap b/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/sitemap.xmap deleted file mode 100644 index 4bfb9021d902c8f6187072c627dc9e9923b846de..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/webapp/themes/Participatorio/sitemap.xmap +++ /dev/null @@ -1,169 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - 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/ - ---> -<map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> - - <map:components> - <map:readers> - <map:reader name="ConcatenationReader" src="org.dspace.app.xmlui.cocoon.ConcatenationReader"/> - </map:readers> - </map:components> - - <map:pipelines> - - <!-- - Define global theme variables that are used later in this - sitemap. Two variables are typically defined here, the theme's - path and name. The path is the directory name where this theme - is located, such as "Reference" for the reference theme. The - theme's name is used only for descriptive purposes to describe - the theme. - --> - <map:component-configurations> - <global-variables> - <theme-path>Participatorio</theme-path> - <theme-name>Participatorio</theme-name> - </global-variables> - </map:component-configurations> - - - <map:pipeline> - <!-- Allow the browser to cache static content for an hour --> - <map:parameter name="expires" value="access plus 1 hours"/> - - - <!-- handle static js and css --> - <map:match pattern="themes/*/**.js"> - <map:read type="ConcatenationReader" src="{2}.js"> - <map:parameter name="requestQueryString" value="{request:queryString}"/> - </map:read> - </map:match> - <map:match pattern="themes/*/**.css"> - <map:read type="ConcatenationReader" src="{2}.css"> - <map:parameter name="requestQueryString" value="{request:queryString}"/> - </map:read> - </map:match> - <map:match pattern="themes/*/**.json"> - <map:read type="ConcatenationReader" src="{2}.json"> - <map:parameter name="requestQueryString" value="{request:queryString}"/> - </map:read> - </map:match> - - <!-- Static content --> - <map:match pattern="themes/*/**"> - <map:read src="{2}"/> - </map:match> - </map:pipeline> - - <!-- - The theme's pipeline is used to process all requests handled - by the theme. It is broken up into two parts, the first part - handles all static theme content while the second part handle - all dynamic aspect generated content. The static content is - such things as stylesheets, images, or static pages. Typically - these are just stored on disk and passed directly to the - browser without any processing. - --> - <map:pipeline> - <!-- Never allow the browser to cache dynamic content --> - <map:parameter name="expires" value="now"/> - - <!-- Aspect content - - There are five steps to processing aspect content: - - 1: Generate the DRI page - - The first step is to generate a DRI page for the request; - this is handled by the aspect chain. Once it is generated - it is the beginning of a theme's pipeline, the DRI page is - ultimately transformed in the resulting XHTML that is - given to the user's browser. - - 2: Add page metadata - - The next step is to add theme specific metadata to the - DRI page. This is metadata about where the theme is - located and its name. Typically this metadata is different - depending on the users browser, this allows us to give - different stylesheets to Internet Explorer than for other - browsers. - - 3: Transform to XHTML - - The third step is the main component of a theme the XSL - transformations will turn the DRI page from the aspects - into an XHTML page useable by browsers. - - 4: Localize the page - - The second to last step is to localize the content for the - particular user, if they user is requesting a page in a - particular language then those language strings are inserted - into the resulting XHTML. - - 5: Serialize to the browser - - The last step sends the page to the user's browser. - - --> - <map:match pattern="**"> - - <!-- Step 1: Generate the DRI page --> - <map:generate type="file" src="cocoon://DRI/{1}"/> - - <!-- Step 2 Add page metadata --> - - <!--3 different IncludePageMeta transformers to ensure that the - stylesheets end up in the correct order--> - <map:transform type="IncludePageMeta"> - <map:parameter name="stylesheet.screen#1" value="lib/css/reset.css"/> - <map:parameter name="stylesheet.screen#2" value="lib/css/base.css"/> - <map:parameter name="stylesheet.screen#3" value="lib/css/helper.css"/> - <map:parameter name="stylesheet.screen#4" value="lib/css/jquery-ui-1.8.15.custom.css"/> - <map:parameter name="stylesheet.screen#5" value="lib/css/style.css"/> - <map:parameter name="stylesheet.screen#6" value="lib/css/authority-control.css"/> - </map:transform> - - <map:transform type="IncludePageMeta"> - <map:parameter name="stylesheet.handheld" value="lib/css/handheld.css"/> - <map:parameter name="stylesheet.print" value="lib/css/print.css"/> - </map:transform> - - <map:transform type="IncludePageMeta"> - <map:parameter name="stylesheet.all" value="lib/css/media.css"/> - <map:parameter name="javascript" value="lib/js/jquery-ui-1.8.15.custom.min.js"/> - <map:parameter name="theme.path" value="{global:theme-path}"/> - <map:parameter name="theme.name" value="{global:theme-name}"/> - </map:transform> - - <!-- Debuging output --> - <map:match type="request" pattern="XML"> - <map:serialize type="xml"/> - </map:match> - - <!-- Step 3: Transform to XHTML --> - <map:transform src="Participatorio.xsl"/> - - - <!-- Step 4: Localize the page --> - <map:act type="locale"> - <map:transform type="i18n"> - <map:parameter name="locale" value="{locale}"/> - </map:transform> - </map:act> - - <!-- Step 5: Serialize to the browser --> - <map:serialize type="xhtml"/> - - </map:match> - </map:pipeline> - </map:pipelines> -</map:sitemap> 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 index 90979f71c9148065b91695a1dccc3a95f3cb3c39..6eeba3723af3e2cd115d795a6c5fc1af19796104 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,11 @@ <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> <packaging>pom</packaging> - <version>3.2</version> + <version>4.1</version> <name>DSpace Parent Project</name> + <description> + DSpace open source software is a turnkey institutional repository application. + </description> <url>https://github.com/dspace/DSpace</url> <organization> @@ -18,12 +21,16 @@ <groupId>org.sonatype.oss</groupId> <artifactId>oss-parent</artifactId> <version>7</version> + <relativePath /> </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> + <java.version>1.6</java.version> <!-- DSpace requires Java 1.6 or higher --> + <lucene.version>4.4.0</lucene.version> + <solr.version>4.4.0</solr.version> + <slf4j.version>1.6.1</slf4j.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> @@ -35,12 +42,11 @@ <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> + <source>${java.version}</source> + <target>${java.version}</target> </configuration> </plugin> <plugin> @@ -106,6 +112,38 @@ <!-- These plugin settings only apply to this single POM and are not inherited to any submodules. --> <plugins> + <!-- Ensure that any *.properties files have UTF-8 chars encoded (e.g. "\u00e9") *before* using them to filter dspace.cfg and other configs --> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <version>1.7</version> + <executions> + <execution> + <id>native2ascii-utf8</id> + <phase>generate-resources</phase> + <configuration> + <target name="Encode any UTF-8 chars in [src]/*.properties"> + <!-- Run 'native2ascii' to encode UTF-8 characters in properties files. Place the resulting file(s) in /target --> + <native2ascii encoding="UTF8" src="${root.basedir}" dest="${root.basedir}/target" includes="*.properties" /> + </target> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + <!-- Required dependencies for native2ascii to function --> + <dependencies> + <dependency> + <groupId>com.sun</groupId> + <artifactId>tools</artifactId> + <version>${java.version}</version> + <scope>system</scope> + <!-- Path to tools.jar (containing native2ascii tool) is determined by a profile (see below) --> + <systemPath>${toolsjar}</systemPath> + </dependency> + </dependencies> + </plugin> + <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.3.2</version> @@ -187,7 +225,8 @@ </activation> <properties> <!-- 'root.basedir' is the relative path to the [dspace-src] root folder --> - <filters.file>${root.basedir}/build.properties</filters.file> + <!-- NOTE that we are using the copy in the target dir, which has any Unicode characters encoded (see native2ascii above) --> + <filters.file>${root.basedir}/target/build.properties</filters.file> </properties> </profile> @@ -204,7 +243,8 @@ </activation> <properties> <!-- 'root.basedir' is the relative path to the [dspace-src] root folder --> - <filters.file>${root.basedir}/${env}.properties</filters.file> + <!-- NOTE that we are using the copy in the target dir, which has any Unicode characters encoded (see native2ascii above) --> + <filters.file>${root.basedir}/target/${env}.properties</filters.file> </properties> </profile> @@ -247,6 +287,33 @@ </build> </profile> + <!-- Determine path to Java Tools JAR. This JAR contains the 'native2ascii' tool (required above by maven-antrun-plugin)--> + <!-- In most platforms Unix/Windows it's named tools.jar. But, on Mac it's classes.jar (see next profile) --> + <profile> + <id>default-java-tools</id> + <activation> + <activeByDefault>true</activeByDefault> + <file> + <exists>${java.home}/../lib/tools.jar</exists> + </file> + </activation> + <properties> + <toolsjar>${java.home}/../lib/tools.jar</toolsjar> + </properties> + </profile> + <profile> + <id>mac-java-tools</id> + <activation> + <activeByDefault>false</activeByDefault> + <file> + <exists>${java.home}/../Classes/classes.jar</exists> + </file> + </activation> + <properties> + <toolsjar>${java.home}/../Classes/classes.jar</toolsjar> + </properties> + </profile> + <!-- These profiles activate the inclusion of various modules into @@ -330,6 +397,19 @@ </modules> </profile> + <!-- REST Jersey --> + <profile> + <id>dspace-rest</id> + <activation> + <file> + <exists>dspace-rest/pom.xml</exists> + </file> + </activation> + <modules> + <module>dspace-rest</module> + </modules> + </profile> + <!-- Builds SWORD WAR for DSpace @@ -346,6 +426,22 @@ </modules> </profile> + + <!-- + Builds SOLR WAR for DSpace + --> + <profile> + <id>dspace-solr</id> + <activation> + <file> + <exists>dspace-solr/pom.xml</exists> + </file> + </activation> + <modules> + <module>dspace-solr</module> + </modules> + </profile> + <!-- Builds SWORDv2 WAR for DSpace --> @@ -410,6 +506,7 @@ <module>dspace-xmlui</module> <module>dspace-lni</module> <module>dspace-oai</module> + <module>dspace-rest</module> <module>dspace-sword</module> <module>dspace-swordv2</module> </modules> @@ -430,6 +527,7 @@ <maven.test.skip>true</maven.test.skip> </properties> </profile> + </profiles> <!-- @@ -445,113 +543,113 @@ <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-api</artifactId> - <version>3.2</version> + <version>4.1</version> </dependency> <dependency> <groupId>org.dspace.modules</groupId> <artifactId>additions</artifactId> - <version>3.2</version> + <version>4.1</version> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-sword</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-sword</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-swordv2</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-swordv2</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-jspui</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-jspui</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-oai</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-oai</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-lni</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-lni-client</artifactId> - <version>4.0-SNAPSHOT</version> + <version>4.1</version> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-lni</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-xmlui</artifactId> - <version>3.2</version> + <version>4.1</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-xmlui</artifactId> - <version>3.2</version> + <version>4.1</version> <type>war</type> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-services</artifactId> - <version>3.2</version> + <version>4.1</version> </dependency> <!-- DSpace Localization Packages --> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-api-lang</artifactId> - <version>[3.0.2,4.0.0)</version> + <version>[4.0.0,5.0.0)</version> </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-xmlui-lang</artifactId> - <version>[3.0.2,4.0.0)</version> + <version>[4.0.0,5.0.0)</version> <type>war</type> </dependency> <!-- DSpace third Party Dependencies --> @@ -622,9 +720,14 @@ </dependency> <dependency> <groupId>org.apache.lucene</groupId> - <artifactId>lucene-analyzers</artifactId> + <artifactId>lucene-analyzers-common</artifactId> <version>${lucene.version}</version> </dependency> + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-queryparser</artifactId> + <version>${lucene.version}</version> + </dependency> <dependency> <groupId>org.dspace</groupId> <artifactId>handle</artifactId> @@ -648,7 +751,7 @@ <dependency> <groupId>commons-cli</groupId> <artifactId>commons-cli</artifactId> - <version>1.0</version> + <version>1.2</version> </dependency> <dependency> <groupId>commons-codec</groupId> @@ -697,11 +800,11 @@ <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>commons-validator</groupId> + <artifactId>commons-validator</artifactId> + <version>1.4.0</version> + </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> @@ -710,7 +813,7 @@ <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> - <version>2.4</version> + <version>2.5</version> </dependency> <dependency> @@ -732,7 +835,7 @@ <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> - <version>1.2.14</version> + <version>1.2.17</version> </dependency> <dependency> <groupId>oro</groupId> @@ -840,7 +943,7 @@ <dependency> <groupId>com.ibm.icu</groupId> <artifactId>icu4j</artifactId> - <version>3.8</version> + <version>51.1</version> </dependency> <dependency> <groupId>postgresql</groupId> @@ -872,6 +975,26 @@ <artifactId>commons-httpclient</artifactId> <version>3.1</version> </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-jdk14</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>${slf4j.version}</version> + </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> @@ -896,6 +1019,12 @@ <version>1.06</version> <scope>test</scope> </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.2.1</version> + <scope>compile</scope> + </dependency> </dependencies> </dependencyManagement> @@ -1180,7 +1309,7 @@ <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> + <tag>dspace-4.1</tag> </scm> <!-- 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