jabref/branches/upstream/current.
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src/java"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="lib" path="lib/aelfred-1.2.jar"/>
- <classpathentry kind="lib" path="lib/antlr.jar"/>
- <classpathentry kind="lib" path="lib/ccl.jar"/>
- <classpathentry kind="lib" path="lib/jalopy-1.0b10.jar"/>
- <classpathentry kind="lib" path="lib/jalopy-ant-0.6.1.jar"/>
- <classpathentry kind="lib" path="lib/javancss.jar"/>
- <classpathentry kind="lib" path="lib/jaxen-core-1.0-fcs.jar"/>
- <classpathentry kind="lib" path="lib/jaxp-1.2.jar"/>
- <classpathentry kind="lib" path="lib/jdom-1.0b8.jar"/>
- <classpathentry kind="lib" path="lib/log4j-1.2.6.jar"/>
- <classpathentry kind="lib" path="lib/looks-1.2.2.jar"/>
- <classpathentry kind="lib" path="lib/oro-2.0.6.jar"/>
- <classpathentry kind="lib" path="lib/plastic-1.2.1.jar"/>
- <classpathentry kind="lib" path="lib/sax-2.0.1.jar"/>
- <classpathentry kind="lib" path="lib/saxpath-1.0-fcs.jar"/>
- <classpathentry kind="lib" path="lib/vizant.jar"/>
- <classpathentry kind="lib" path="lib/spin.jar"/>
- <classpathentry kind="var" path="JUNIT_HOME/junit.jar"/>
- <classpathentry kind="lib" path="lib/pmd-2.0.jar"/>
- <classpathentry kind="lib" path="lib/forms-1.0.4.jar"/>
- <classpathentry kind="lib" path="lib/junit.jar"/>
- <classpathentry kind="lib" path="lib/log4j-1.2.9.jar"/>
- <classpathentry kind="output" path="build"/>
-</classpath>
+++ /dev/null
-bak
-build
-.classpath
-.project
-work.jpx
-work.refactor
-.#build.xml.1.38
-.#jabref.log.1.2
-ini
-jabref.log
-jabref.log.lck
-build.number
-classes
-jabref.jpx
-jabref.oif
#Build Number for ANT. Do not edit!
-#Wed Aug 09 18:35:54 CEST 2006
-build.number=570
+#Sun Nov 26 20:22:40 CET 2006
+build.number=341
Compiler: Ant
Authors: Joerg K. Wegner, wegnerj@informatik.uni-tuebingen.de
Morten O. Alver
- Version: $Revision: 1.62 $
- $Date: 2006/07/25 19:56:36 $
- $Author: mortenalver $
+ Version: $Revision: 1.77 $
+ $Date: 2006/11/23 22:37:19 $
+ $Author: coezbek $
modified:
+ 23.11.2006 c.oezbek
+ - tried to fix classpath issues
28.07.2005 r.nagel
- insert dynamic build info generation (resource/build.properties)
- copy fonts directory, used by the new about dialog
<project name="JabRef" default="jars" basedir=".">
- <!-- ==========================================================================================
+ <!-- ==========================================================================================
PROPERTY SETUP
========================================================================================== -->
- <!-- some version information -->
- <property name="jabref.bin" value="jabref" />
- <property name="jabref.version" value="2.1" />
- <property name="jabref.placeholder.version" value="@version@" /> <!-- used by replace task -->
-
-
- <!-- Set the properties for intermediate directory -->
- <property name="build.dir" value="build" />
- <property name="build.classes" value="${build.dir}/classes" />
- <property name="build.tmp" value="${build.dir}/tmp" />
- <property name="build.osx" value="${build.dir}/classes/osxadapter" />
- <property name="build.lib" value="${build.dir}/lib" />
- <property name="build.bin" value="${build.dir}/bin" />
- <property name="build.win" value="${build.dir}/windows" />
- <property name="build.images" value="${build.dir}/images" />
- <property name="build.fonts" value="${build.dir}/images/font" />
- <property name="build.resource" value="${build.dir}/resource" />
- <property name="build.help" value="${build.dir}/help" />
- <property name="build.javadocs" value="${build.dir}/docs/API" />
- <property name="build.extensions" value="${build.dir}/extensions" />
- <property name="build.extension-javadocs" value="${build.extensions}/API" />
- <property name="build.extension-layout" value="${build.extensions}/layout" />
- <property name="build.openoffice.meta" value="${build.resource}/openoffice"/>
-
- <!-- Set the properties for source directories -->
- <property name="src.dir" value="src" />
- <property name="src.tests" value="src/java/tests" />
- <property name="txt.dir" value="src/txt" />
- <property name="java.dir" value="${src.dir}/java" />
- <property name="osx.dir" value="${src.dir}/osx" />
- <property name="win.dir" value="${src.dir}/windows" />
- <property name="resource.dir" value="${src.dir}/resource" />
- <property name="bin.dir" value="${src.dir}/scripts" />
- <property name="images.dir" value="${src.dir}/images" />
- <property name="fonts.dir" value="${src.dir}/images/font" />
- <property name="help.dir" value="${src.dir}/help" />
- <property name="extensions.dir" value="${src.dir}/extensions" />
- <property name="layout.dir" value="${src.dir}/resource/layout" />
-
-
- <!-- Set the properties for library directories -->
- <property name="library.directory" value="lib" />
-
-
- <taskdef name="jarbundler"
- classpath="${library.directory}/jarbundler-1.4.jar"
- classname="com.loomcom.ant.tasks.jarbundler.JarBundler" />
-
-
- <!-- Build classpath -->
- <path id="classpath">
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </path>
-
- <!-- Runs project (e.g. in NetBeans 4) -->
- <target name="run" depends="jars">
- <java classname="net.sf.jabref.JabRef" fork="true">
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- <pathelement location="${library.directory}/microba.jar" />
- </classpath>
- </java>
- </target>
-
- <!-- Target used for profiling with the Netbeans profiler. -->
- <!--<target name="profile" depends="jars">
- <nbprofile classname="net.sf.jabref.JabRef">
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- </classpath>
- </nbprofile>
- </target>-->
- <target name="profile" depends="jars" description="Profile JabRef">
- <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
-
- <nbprofiledirect>
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- </classpath>
- </nbprofiledirect>
-
- <property environment="env"/>
- <java fork="true" classname="net.sf.jabref.JabRef" dir="${build.dir}"
- jvm="${profiler.info.jvm}">
- <jvmarg value="${profiler.info.jvmargs.agent}"/>
- <jvmarg line="${profiler.info.jvmargs}"/>
- <env key="LD_LIBRARY_PATH" path="${profiler.info.agentpath}:${env.LD_LIBRARY_PATH}"/>
- <classpath>
- <pathelement location="${build.lib}/jabref.jar"/>
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
-
- </classpath>
- </java>
- </target>
- <!-- Compiles project -->
- <target name="compile">
- <mkdir dir="${build.classes}" />
- <!--deprecation="on"-->
- <javac debug="off" deprecation="on" destdir="${build.classes}" source="1.4" target="1.4">
- <src path="${java.dir}"/>
- <exclude name="tests/**"/>
- <classpath>
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/forms-1.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- <pathelement location="${library.directory}/glazedlists-1.5.0_java14.jar" />
- <pathelement location="${library.directory}/microba.jar" />
- </classpath>
- </javac>
- </target>
-
- <!-- Compiles only the tests -->
- <target name="compiletest">
- <mkdir dir="${build.classes}" />
- <!--deprecation="on"-->
- <javac srcdir="${java.dir}/tests" debug="off" destdir="${build.classes}" source="1.4" target="1.4">
- <classpath>
- <pathelement path="${build.classes}" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- </classpath>
- </javac>
-
- </target>
- <!-- Builds the OSXAdapter -->
- <target name="osx">
- <mkdir dir="${build.classes}" />
-
- <javac srcdir="${osx.dir}" debug="off" destdir="${build.classes}" target="1.4">
- </javac>
- </target>
-
- <!-- Copies in the OSXAdapter class, which is compilable only on Mac -->
- <target name="non_osx">
- <mkdir dir="${build.osx}" />
- <copy file="${library.directory}/OSXAdapter.class" todir="${build.osx}" />
- </target>
-
-
- <!-- Jars up project -->
- <target name="jars" depends="build">
- <mkdir dir="${build.lib}" />
- <mkdir dir="${build.tmp}" />
- <jar destfile="${build.lib}/jabref.jar">
- <fileset dir="${build.classes}" />
- <fileset dir="${build.tmp}" />
- <fileset dir="${build.dir}">
- <include name="images/**" />
- <include name="help/**" />
- <include name="help/de/**" />
- <include name="help/no/**" />
- <include name="resource/**" />
- </fileset>
- <fileset dir="${library.directory}">
- <include name="EndNote.zip" />
- </fileset>
-
- <fileset dir="${txt.dir}">
- <include name="gpl.txt" />
- <include name="lesser.txt" />
- <include name="apache-license.txt" />
- <include name="jgoodies.txt" />
- <include name="README" />
- </fileset>
- <manifest>
- <attribute name="Main-Class" value="net.sf.jabref.JabRef" />
-<!-- <attribute name="Main-Class" value="net.sf.jabref.gui.FieldWeightDialog" /> -->
- </manifest>
- </jar>
-
- </target>
-
- <!-- copy all necessary files and insert version informations -->
- <target name="build" depends="compile, buildinfos" description="Build project">
- <mkdir dir="${build.bin}" />
-
- <mkdir dir="${build.resource}" />
- <copy todir="${build.resource}">
- <fileset dir="${resource.dir}">
- <include name="**" />
- </fileset>
- </copy>
- <mkdir dir="${build.images}" />
- <copy todir="${build.images}">
- <fileset dir="${images.dir}">
- <include name="**" />
- </fileset>
- </copy>
-
- <!-- the fonts are used by the new about dialog -->
- <mkdir dir="${build.fonts}" />
- <copy todir="${build.fonts}">
- <fileset dir="${fonts.dir}">
- <include name="*" />
- </fileset>
- </copy>
-
- <mkdir dir="${build.help}" />
- <copy todir="${build.help}">
- <fileset dir="${help.dir}">
- <!--<include name="*" />-->
- </fileset>
- </copy>
-
- <!-- Insert version informations -->
- <replace dir="${build.help}"
- token="${jabref.placeholder.version}"
- value="${jabref.version}">
- <include name="**/About.html"/>
- </replace>
- <replace dir="${build.openoffice.meta}"
- token="${jabref.placeholder.version}"
- value="${jabref.version}">
- <include name="meta.xml"/>
- </replace>
-
-<!-- WHY ???
- <mkdir dir="${build.win}" />
- <copy file="${build.lib}/${jabref.bin}.jar" todir="${build.win}" />
- <copy todir="${build.win}">
- <fileset dir="${win.dir}">
- <include name="*" />
- </fileset>
- </copy>
--->
- </target>
-
-<!-- generate and save some build infos !!! necessary for dynamic build infos !!! -->
-<!-- todo : replace it by the replace task :-),
+ <!-- some version information -->
+ <property name="jabref.bin" value="JabRef-2.2" />
+ <property name="jabref.version" value="2.2b2" />
+ <property name="jabref.placeholder.version" value="@version@" />
+ <!-- used by replace task -->
+
+
+ <!-- Set the properties for intermediate directory -->
+ <property name="build.dir" value="build" />
+ <property name="build.classes" value="${build.dir}/classes" />
+ <property name="build.tmp" value="${build.dir}/tmp" />
+ <property name="build.osx" value="${build.dir}/classes/osxadapter" />
+ <property name="build.lib" value="${build.dir}/lib" />
+ <property name="build.win" value="${build.dir}/windows" />
+ <property name="build.images" value="${build.dir}/images" />
+ <property name="build.fonts" value="${build.dir}/images/font" />
+ <property name="build.resource" value="${build.dir}/resource" />
+ <property name="build.help" value="${build.dir}/help" />
+ <property name="build.javadocs" value="${build.dir}/docs/API" />
+ <property name="build.extensions" value="${build.dir}/extensions" />
+ <property name="build.extension-javadocs" value="${build.extensions}/API" />
+ <property name="build.extension-layout" value="${build.extensions}/layout" />
+ <property name="build.openoffice.meta" value="${build.resource}/openoffice" />
+
+ <!-- Set the properties for source directories -->
+ <property name="src.dir" value="src" />
+ <property name="src.tests" value="src/java/tests" />
+ <property name="txt.dir" value="src/txt" />
+ <property name="java.dir" value="${src.dir}/java" />
+ <property name="osx.dir" value="${src.dir}/osx" />
+ <property name="win.installer.dir" value="${src.dir}/windows/nsis" />
+ <property name="resource.dir" value="${src.dir}/resource" />
+ <property name="bin.dir" value="${src.dir}/scripts" />
+ <property name="images.dir" value="${src.dir}/images" />
+ <property name="fonts.dir" value="${src.dir}/images/font" />
+ <property name="help.dir" value="${src.dir}/help" />
+ <property name="extensions.dir" value="${src.dir}/extensions" />
+ <property name="layout.dir" value="${src.dir}/resource/layout" />
+
+ <!-- Set the properties for library directories -->
+ <property name="library.directory" value="lib" />
+
+ <!-- Load user dependent properties -->
+ <property file="build.properties" />
+ <!--
+ * For instance define the NSIS-compiler:
+ * nsis.executable="d:\prog\dev\NSIS\makensis.exe"
+ *-->
+
+ <!-- win.installer can only be build under Windows -->
+ <condition property="is.windows">
+ <and>
+ <os family="windows" />
+ <isset property="nsis.executable" />
+ </and>
+ </condition>
+
+ <taskdef name="jarbundler" classpath="${library.directory}/jarbundler-1.4.jar" classname="com.loomcom.ant.tasks.jarbundler.JarBundler" />
+
+
+ <!-- Build classpath -->
+ <path id="classpath">
+ <pathelement path="${build.classes}" />
+ <pathelement path="${build.dir}" />
+ <pathelement location="${library.directory}/antlr.jar" />
+ <pathelement location="${library.directory}/antlr-3.0b5.jar" />
+ <pathelement location="${library.directory}/looks-2.0.4.jar" />
+ <pathelement location="${library.directory}/forms-1.0.4.jar" />
+ <pathelement location="${library.directory}/spin.jar" />
+ <pathelement location="${library.directory}/glazedlists-1.7.0_java14.jar" />
+ <pathelement location="${library.directory}/microba.jar" />
+ <pathelement location="${library.directory}/PDFBox-0.7.3-dev-reduced.jar" />
+ <pathelement location="${library.directory}/JempBox-0.1.0-dev.jar" />
+ </path>
+
+ <target name="run" depends="build">
+ <java classname="net.sf.jabref.JabRef" fork="true">
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+ <!-- Runs project -->
+ <target name="runFromJar" depends="jars">
+ <java classname="net.sf.jabref.JabRef" fork="true">
+ <classpath>
+ <pathelement location="${build.lib}/jabref.jar" />
+ </classpath>
+ </java>
+ </target>
+
+ <target name="profile" depends="jars" description="Profile JabRef">
+ <fail unless="netbeans.home">This target can only run inside the NetBeans IDE.</fail>
+
+ <nbprofiledirect>
+ <classpath refid="classpath"/>
+ </nbprofiledirect>
+
+ <property environment="env" />
+ <java fork="true" classname="net.sf.jabref.JabRef" dir="${build.dir}" jvm="${profiler.info.jvm}">
+ <jvmarg value="${profiler.info.jvmargs.agent}" />
+ <jvmarg line="${profiler.info.jvmargs}" />
+ <env key="LD_LIBRARY_PATH" path="${profiler.info.agentpath}:${env.LD_LIBRARY_PATH}" />
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
+ <!-- Compiles project -->
+ <target name="compile">
+ <mkdir dir="${build.classes}" />
+ <javac debug="on" deprecation="on" destdir="${build.classes}" source="1.4" target="1.4">
+ <src path="${java.dir}" />
+ <exclude name="tests/**" />
+ <classpath refid="classpath"/>
+ </javac>
+ </target>
+
+ <!-- Compiles only the tests -->
+ <target name="compiletest">
+ <mkdir dir="${build.classes}" />
+ <!--deprecation="on"-->
+ <javac srcdir="${java.dir}/tests" debug="off" destdir="${build.classes}" source="1.4" target="1.4">
+ <classpath refid="classpath"/>
+ </javac>
+ </target>
+
+ <!-- Builds the OSXAdapter -->
+ <target name="osx">
+ <mkdir dir="${build.classes}" />
+
+ <javac srcdir="${osx.dir}" debug="on" destdir="${build.classes}" target="1.4">
+ </javac>
+ </target>
+
+ <!-- Copies in the OSXAdapter class, which is compilable only on Mac -->
+ <target name="non_osx">
+ <mkdir dir="${build.osx}" />
+ <copy file="${library.directory}/OSXAdapter.class" todir="${build.osx}" />
+ </target>
+
+ <!-- Jars up project -->
+ <target name="jars" depends="build, unjarlib">
+ <mkdir dir="${build.lib}" />
+ <mkdir dir="${build.tmp}" />
+ <jar destfile="${build.lib}/jabref.jar">
+
+ <fileset dir="${build.classes}" />
+ <fileset dir="${build.tmp}" />
+ <fileset dir="${build.dir}">
+ <include name="images/**" />
+ <include name="help/**" />
+ <include name="help/de/**" />
+ <include name="help/no/**" />
+ <include name="resource/**" />
+ </fileset>
+ <fileset dir="${library.directory}">
+ <include name="EndNote.zip" />
+ </fileset>
+ <fileset dir="${txt.dir}">
+ <include name="gpl.txt" />
+ <include name="lesser.txt" />
+ <include name="jgoodies.txt" />
+ <include name="README" />
+ </fileset>
+ <manifest>
+ <attribute name="Main-Class" value="net.sf.jabref.JabRef" />
+ </manifest>
+ </jar>
+
+ </target>
+
+ <!-- copy all necessary files and insert version informations -->
+ <target name="build" depends="compile, buildinfos" description="Build project">
+
+ <mkdir dir="${build.resource}" />
+
+ <copy todir="${build.resource}">
+ <fileset dir="${resource.dir}">
+ <include name="**" />
+ </fileset>
+ </copy>
+ <mkdir dir="${build.images}" />
+ <copy todir="${build.images}">
+ <fileset dir="${images.dir}">
+ <include name="**" />
+ </fileset>
+ </copy>
+
+ <!-- the fonts are used by the new about dialog
+ <mkdir dir="${build.fonts}" />
+ <copy todir="${build.fonts}">
+ <fileset dir="${fonts.dir}">
+ <include name="*" />
+ </fileset>
+ </copy> -->
+
+ <mkdir dir="${build.help}" />
+ <copy todir="${build.help}">
+ <fileset dir="${help.dir}">
+ <!--<include name="*" />-->
+ </fileset>
+ </copy>
+
+ <!-- Insert version informations -->
+ <replace dir="${build.help}" token="${jabref.placeholder.version}" value="${jabref.version}">
+ <include name="**/About.html" />
+ </replace>
+ <replace dir="${build.openoffice.meta}" token="${jabref.placeholder.version}" value="${jabref.version}">
+ <include name="meta.xml" />
+ </replace>
+
+ </target>
+
+ <!-- generate and save some build infos !!! necessary for dynamic build infos !!! -->
+ <!-- todo : replace it by the replace task :-),
src/resource/build.properties = template
build/resource/build.properties = real info file
--->
- <target name="buildinfos">
- <tstamp/> <!-- get date -->
- <buildnumber/> <!-- generate new build number -> build.number -->
- <echo message="build number = ${build.number}"/>
- <!-- write the file, please do not edit this lines -->
- <echo file="${resource.dir}/build.properties">builddate=${TODAY}
+ -->
+ <target name="buildinfos">
+ <tstamp />
+ <!-- get date -->
+ <buildnumber />
+ <!-- generate new build number -> build.number -->
+ <echo message="build number = ${build.number}" />
+ <!-- write the file, please do not edit this lines -->
+ <echo file="${resource.dir}/build.properties">builddate=${TODAY}
build=${build.number}
version=${jabref.version}</echo>
- </target>
-
-
- <!-- Creates all docs -->
- <target name="docs" depends="javadocs" description="Generates all the documentation" />
-
- <!-- Creates javadocs -->
- <target name="javadocs" depends="compile" description="Generates the javadocs">
- <mkdir dir="${build.javadocs}" />
- <javadoc sourcepath="${java.dir}" destdir="${build.javadocs}" author="true" version="true" windowtitle="JabRef API" link="http://java.sun.com/j2se/1.4.1/docs/api/">
-
- <fileset dir="${java.dir}" defaultexcludes="yes">
- <include name="**/*.java" />
- </fileset>
-
- <classpath refid="classpath" />
- </javadoc>
- </target>
-
- <!-- Creates javadocs for the extensions -->
- <target name="extension-javadocs" depends="build" description="Generates the javadocs for the extensions archive">
- <mkdir dir="${build.extension-javadocs}" />
- <copy todir="${build.extension-javadocs}">
- <fileset dir="${help.dir}" defaultexcludes="yes">
- <include name="CustomExports.html" />
- <include name="CustomImports.html" />
- </fileset>
- </copy>
-
- <javadoc sourcepath="${java.dir}"
- destdir="${build.extension-javadocs}"
- author="true"
- version="true"
- windowtitle="JabRef-Extensions API"
- link="http://java.sun.com/j2se/1.4.1/docs/api/"
- Overview="${extensions.dir}/API/overview.html"
- access="protected"
- >
- <!--
- create javadoc only selectively for classes that
- users extending JabRef are likely to use
- -->
- <fileset dir="${java.dir}" defaultexcludes="yes">
- <include name="net/sf/jabref/imports/ImportFormat.java" />
- <include name="net/sf/jabref/imports/ImportFormatReader.java" />
- <include name="net/sf/jabref/BibtexEntry.java" />
- <include name="net/sf/jabref/BibtexEntryType.java" />
- <include name="net/sf/jabref/AuthorList.java" />
- <include name="net/sf/jabref/AuthorList.java" />
- <include name="net/sf/jabref/export/layout/LayoutFormatter.java" />
- </fileset>
-
- <classpath refid="classpath" />
- </javadoc>
- </target>
-
- <!-- Creates javadocs for the extensions -->
- <target name="extensions" depends="extension-javadocs" description="Generates the extensions archive">
- <!-- copy examples -->
- <copy todir="${build.extensions}">
- <fileset dir="${java.dir}">
- <include name="net/sf/jabref/export/layout/format/CurrentDate.java"/>
- <include name="net/sf/jabref/export/layout/format/ToLowerCase.java"/>
- <include name="net/sf/jabref/export/layout/format/HTMLChars.java"/>
- <include name="net/sf/jabref/imports/*Importer.java"/>
- </fileset>
- </copy>
- <mkdir dir="${build.extension-layout}" />
- <copy todir="${build.extension-layout}">
- <fileset dir="${layout.dir}" />
- </copy>
- <copy todir="${build.extensions}">
- <fileset dir="${extensions.dir}" />
- <filterset>
- <filter token="version" value="${jabref.version}"/>
- </filterset>
- </copy>
- <!-- create extensions-zip file -->
- <zip destfile="${build.dir}/jabref-extensions.zip">
- <zipfileset dir="${build.extensions}" prefix="jabref-extensions"/>
- </zip>
- </target>
-
- <target name="clean" description="Clean project">
- <delete dir="${build.dir}" />
- </target>
-
- <!-- Unpacks jar needed jar files from lib directory into temp directory. -->
- <target name="unjarlib" description="Unpacks jars from library">
- <mkdir dir="${build.tmp}"/>
- <!--<unjar src="${library.directory}/commons-httpclient-2.0.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/commons-logging.jar" dest="${build.tmp}" />-->
- <unjar src="${library.directory}/antlr.jar" dest="${build.tmp}" />
- <!-- <unjar src="${library.directory}/plastic-1.2.1.jar" dest="${build.classes}" />-->
- <unjar src="${library.directory}/looks-2.0.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/forms-1.0.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/spin-1.4.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/glazedlists-1.5.0_java14.jar" dest="${build.tmp}" />
- <unjar src="${library.directory}/microba.jar" dest="${build.tmp}" />
- <delete dir="${build.tmp}/META-INF"/>
- <!-- rename the microba license file -->
- <move file="${build.tmp}/license.txt" tofile="${build.tmp}/microba-license.txt"/>
- </target>
-
-
- <target name="osxjar">
- <jarbundler dir="${build.lib}"
- name="JabRef"
- mainclass="net.sf.jabref.JabRef"
- jars="${build.lib}/${jabref.bin}.jar"
- icon="${images.dir}/JabRef-Logo.icns"
- version="${jabref.version}"
- jvmversion="1.4+"
- stubfile="${library.directory}/JavaApplicationStub" />
-
- </target>
-
-
- <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ </target>
+
+
+ <!-- Creates all docs -->
+ <target name="docs" depends="javadocs" description="Generates all the documentation" />
+
+ <!-- Creates javadocs -->
+ <target name="javadocs" depends="compile" description="Generates the javadocs">
+ <mkdir dir="${build.javadocs}" />
+ <javadoc sourcepath="${java.dir}" destdir="${build.javadocs}" author="true" version="true" windowtitle="JabRef API" link="http://java.sun.com/j2se/1.4.1/docs/api/">
+
+ <fileset dir="${java.dir}" defaultexcludes="yes">
+ <include name="**/*.java" />
+ </fileset>
+
+ <classpath refid="classpath" />
+ </javadoc>
+ </target>
+
+ <!-- Creates javadocs for the extensions -->
+ <target name="extension-javadocs" depends="build" description="Generates the javadocs for the extensions archive">
+ <mkdir dir="${build.extension-javadocs}" />
+ <copy todir="${build.extension-javadocs}">
+ <fileset dir="${help.dir}" defaultexcludes="yes">
+ <include name="CustomExports.html" />
+ <include name="CustomImports.html" />
+ </fileset>
+ </copy>
+
+ <javadoc sourcepath="${java.dir}" destdir="${build.extension-javadocs}" author="true" version="true" windowtitle="JabRef-Extensions API" link="http://java.sun.com/j2se/1.4.1/docs/api/" Overview="${extensions.dir}/API/overview.html" access="protected">
+ <!--
+ create javadoc only selectively for classes that
+ users extending JabRef are likely to use
+ -->
+ <fileset dir="${java.dir}" defaultexcludes="yes">
+ <include name="net/sf/jabref/imports/ImportFormat.java" />
+ <include name="net/sf/jabref/imports/ImportFormatReader.java" />
+ <include name="net/sf/jabref/BibtexEntry.java" />
+ <include name="net/sf/jabref/BibtexEntryType.java" />
+ <include name="net/sf/jabref/AuthorList.java" />
+ <include name="net/sf/jabref/AuthorList.java" />
+ <include name="net/sf/jabref/export/layout/LayoutFormatter.java" />
+ </fileset>
+
+ <classpath refid="classpath" />
+ </javadoc>
+ </target>
+
+ <!-- Creates javadocs for the extensions -->
+ <target name="extensions" depends="extension-javadocs" description="Generates the extensions archive">
+ <!-- copy examples -->
+ <copy todir="${build.extensions}">
+ <fileset dir="${java.dir}">
+ <include name="net/sf/jabref/export/layout/format/CurrentDate.java" />
+ <include name="net/sf/jabref/export/layout/format/ToLowerCase.java" />
+ <include name="net/sf/jabref/export/layout/format/HTMLChars.java" />
+ <include name="net/sf/jabref/imports/*Importer.java" />
+ </fileset>
+ </copy>
+ <mkdir dir="${build.extension-layout}" />
+ <copy todir="${build.extension-layout}">
+ <fileset dir="${layout.dir}" />
+ </copy>
+ <copy todir="${build.extensions}">
+ <fileset dir="${extensions.dir}" />
+ <filterset>
+ <filter token="version" value="${jabref.version}" />
+ </filterset>
+ </copy>
+ <!-- create extensions-zip file -->
+ <zip destfile="${build.dir}/jabref-extensions.zip">
+ <zipfileset dir="${build.extensions}" prefix="jabref-extensions" />
+ </zip>
+ </target>
+
+ <target name="clean" depends="win.installer.clean" description="Clean project">
+ <delete dir="${build.dir}" />
+ </target>
+
+ <!-- Unpacks jar needed jar files from lib directory into temp directory. -->
+ <target name="unjarlib" description="Unpacks jars from library">
+ <mkdir dir="${build.tmp}" />
+ <unjar src="${library.directory}/antlr.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/antlr-3.0b5.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/looks-2.0.4.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/forms-1.0.4.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/spin.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/glazedlists-1.7.0_java14.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/microba.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/PDFBox-0.7.3-dev-reduced.jar" dest="${build.tmp}" />
+ <unjar src="${library.directory}/JempBox-0.1.0-dev.jar" dest="${build.tmp}" />
+ <delete dir="${build.tmp}/META-INF" />
+ <!-- rename the microba license file -->
+ <move file="${build.tmp}/license.txt" tofile="${build.tmp}/microba-license.txt" />
+ </target>
+
+
+ <target name="osxjar">
+ <jarbundler dir="${build.lib}" name="JabRef" mainclass="net.sf.jabref.JabRef" jars="${build.lib}/jabref.jar" icon="${images.dir}/JabRef-Logo.icns" version="${jabref.version}" jvmversion="1.4+" stubfile="${library.directory}/JavaApplicationStub" />
+ </target>
+
+
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+ <!-- Build Windows Installer -->
+ <!-- -->
+ <!-- Don't forget to set nsis.executable property -->
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+
+ <target name="win.installer.clean" description="Delete Installer and Exe-Wrapper + Temp-files">
+ <delete dir="${win.installer.dir}/dist" />
+ <delete file="${win.installer.dir}/JabRefSetup.exe" />
+ </target>
+
+ <target name="win.installer.prepare" depends="jars" if="is.windows" description="Copy files in place to be used by the installer">
+ <!-- Gather everything that will go into the installer in dist -->
+ <mkdir dir="${win.installer.dir}/dist" />
+ <!-- <copy file="${build.lib}/${jabref.bin}.jar"
+ todir="${win.installer.dir}/dist" /> -->
+ <copy todir="${win.installer.dir}/dist">
+ <fileset dir="${txt.dir}">
+ <include name="gpl.txt" />
+ <include name="lesser.txt" />
+ <include name="README" />
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="win.installer.exewrapper" depends="win.installer.prepare" if="is.windows" description="Create Exe-Wrapper">
+ <exec dir="." executable="${nsis.executable}" failonerror="true">
+ <arg line="'/DJARFILE=${jabref.bin}.jar' '/DVERSION=${jabref.version}' '/DAPPICON=../../../${images.dir}/JabRef.ico' ${win.installer.dir}/launcher.nsi" />
+ </exec>
+ </target>
+
+ <target name="win.installer.build" depends="win.installer.exewrapper" if="is.windows" description="Create Windows-Installer.">
+ <exec dir="." executable="${nsis.executable}" failonerror="true">
+ <arg line="'/DVERSION=${jabref.version}' ${win.installer.dir}/setup.nsi" />
+ </exec>
+ </target>
+
+ <!--++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
What's about the software design ?!;-)
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
-
- <target name="pmd" description="SOFTWAREDESIGN: Project Mess Detector !;-)">
- <echo>Checking Project Mess Detection (PMD) rulesets.</echo>
- <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <!-- allowed Pretty Much Done rulsets -->
- <!-- rulesets/basic.xml -->
- <!-- rulesets/braces.xml -->
- <!-- rulesets/codesize.xml-->
- <!-- rulesets/controversial.xml-->
- <!-- rulesets/coupling.xml-->
- <!-- rulesets/design.xml -->
- <!-- rulesets/experimental.xml -->
- <!-- rulesets/favorites.xml -->
- <!-- rulesets/imports.xml -->
- <!-- rulesets/naming.xml -->
- <!-- rulesets/javabean.xml -->
- <!-- rulesets/junit.xml -->
- <!-- rulesets/scratchpad.xml -->
- <!-- rulesets/strictexception.xml -->
- <!-- rulesets/strings.xml -->
- <!-- rulesets/unusedcode.xml -->
-
- <pmd rulesetfiles="rulesets/unusedcode.xml,rulesets/basic.xml" failonerror="no">
- <formatter type="html" toFile="${build.dir}/pmd_report.html" />
- <fileset dir="${src.dir}">
- <include name="**/*.java" />
- </fileset>
- </pmd>
-
- <!-- check for duplicated code -->
- <echo>WARNING: use environment variable: ANT_OPTS=-Xmx512m or this task will fail.</echo>
- <echo>Checking for duplicated code using the Copy/Paste Detector (CPD).</echo>
- <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <cpd format="text" minimumTokenCount="100" outputFile="${build.dir}/duplicated_code_report.txt">
- <fileset dir="${src.dir}">
- <include name="**/*.java" />
- </fileset>
- </cpd>
- </target>
-
-
- <target name="javancss" description="SOFTWAREDESIGN: Determining the NCSS and CCN code metrics for JOELib.">
- <taskdef name="javancss" classname="javancss.JavancssAntTask">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <echo>Cyclomatic
+ ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
+
+ <target name="pmd" description="SOFTWAREDESIGN: Project Mess Detector !;-)">
+ <echo>Checking Project Mess Detection (PMD) rulesets.</echo>
+ <taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <!-- allowed Pretty Much Done rulsets -->
+ <!-- rulesets/basic.xml -->
+ <!-- rulesets/braces.xml -->
+ <!-- rulesets/codesize.xml-->
+ <!-- rulesets/controversial.xml-->
+ <!-- rulesets/coupling.xml-->
+ <!-- rulesets/design.xml -->
+ <!-- rulesets/experimental.xml -->
+ <!-- rulesets/favorites.xml -->
+ <!-- rulesets/imports.xml -->
+ <!-- rulesets/naming.xml -->
+ <!-- rulesets/javabean.xml -->
+ <!-- rulesets/junit.xml -->
+ <!-- rulesets/scratchpad.xml -->
+ <!-- rulesets/strictexception.xml -->
+ <!-- rulesets/strings.xml -->
+ <!-- rulesets/unusedcode.xml -->
+
+ <pmd rulesetfiles="rulesets/unusedcode.xml,rulesets/basic.xml" failonerror="no">
+ <formatter type="html" toFile="${build.dir}/pmd_report.html" />
+ <fileset dir="${src.dir}">
+ <include name="**/*.java" />
+ </fileset>
+ </pmd>
+
+ <!-- check for duplicated code -->
+ <echo>WARNING: use environment variable: ANT_OPTS=-Xmx512m or this task will fail.</echo>
+ <echo>Checking for duplicated code using the Copy/Paste Detector (CPD).</echo>
+ <taskdef name="cpd" classname="net.sourceforge.pmd.cpd.CPDTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <cpd format="text" minimumTokenCount="100" outputFile="${build.dir}/duplicated_code_report.txt">
+ <fileset dir="${src.dir}">
+ <include name="**/*.java" />
+ </fileset>
+ </cpd>
+ </target>
+
+
+ <target name="javancss" description="SOFTWAREDESIGN: Determining the NCSS and CCN code metrics for JOELib.">
+ <taskdef name="javancss" classname="javancss.JavancssAntTask">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <echo>Cyclomatic
Complexity Ease of Risk
Number (CCN) maintenance
(McCabe metric)
>50, unstable very hard very high
</echo>
- <javancss srcdir="${src.dir}" includes="**/*.java" excludes="jama/**/*.java, jmat/**/*.java, cformat/**/*.java" abortOnFail="false" ccnPerFuncMax="30" generateReport="true" outputfile="${build.dir}/javancss_report.plain" format="plain" packageMetrics="true" classMetrics="false" functionMetrics="false" />
- </target>
-
- <target name="jalopy" description="SOFTWAREDESIGN: source code formatter using the JOELib convention.">
- <taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
- <classpath>
- <pathelement path="${classpath}" />
- <fileset dir="${library.directory}">
- <include name="*.jar" />
- </fileset>
- </classpath>
- </taskdef>
- <jalopy fileformat="unix" convention="${src.dir}/java/jalopy.format.convention.xml" history="file" historymethod="adler32" loglevel="error" threads="2" classpathref="classpath" backup="bak">
- <fileset dir="${src.dir}">
- <include name="java/net/sf/jabref/**/*.java" />
- </fileset>
- </jalopy>
- </target>
-
- <target name="test">
- <junit printsummary="yes" fork="yes" haltonfailure="no">
- <batchtest fork="yes" todir="/tmp/testres">
- <fileset dir="${build.classes}">
- <include name="**/*Tester.class" />
- <include name="**/*Test.class" />
- </fileset>
- </batchtest>
-
- <classpath>
- <pathelement location="${build.lib}/jabref.jar" />
- <!--<pathelement location="${library.directory}/commons-httpclient-2.0.jar" />
- <pathelement location="${library.directory}/commons-logging.jar" />-->
- <pathelement location="${library.directory}/antlr.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/looks-2.0.4.jar" />
- <pathelement location="${library.directory}/spin-1.4.jar" />
- </classpath>
-
- <!--<test name="tests.net.sf.jabref.export.layout.format.AuthorLastFirstAbbreviatorTester"/>-->
- </junit>
- </target>
-
+ <javancss srcdir="${src.dir}" includes="**/*.java" excludes="jama/**/*.java, jmat/**/*.java, cformat/**/*.java" abortOnFail="false" ccnPerFuncMax="30" generateReport="true" outputfile="${build.dir}/javancss_report.plain" format="plain" packageMetrics="true" classMetrics="false" functionMetrics="false" />
+ </target>
+
+ <target name="jalopy" description="SOFTWAREDESIGN: source code formatter using the JOELib convention.">
+ <taskdef name="jalopy" classname="de.hunsicker.jalopy.plugin.ant.AntPlugin">
+ <classpath>
+ <pathelement path="${classpath}" />
+ <fileset dir="${library.directory}">
+ <include name="*.jar" />
+ </fileset>
+ </classpath>
+ </taskdef>
+ <jalopy fileformat="unix" convention="${src.dir}/java/jalopy.format.convention.xml" history="file" historymethod="adler32" loglevel="error" threads="2" classpathref="classpath" backup="bak">
+ <fileset dir="${src.dir}">
+ <include name="java/net/sf/jabref/**/*.java" />
+ </fileset>
+ </jalopy>
+ </target>
+
+ <target name="test">
+ <junit printsummary="yes" fork="yes" haltonfailure="no">
+ <batchtest fork="yes" todir="/tmp/testres">
+ <fileset dir="${build.classes}">
+ <include name="**/*Tester.class" />
+ <include name="**/*Test.class" />
+ </fileset>
+ </batchtest>
+ <classpath refid="classpath"/>
+ </junit>
+ </target>
+
</project>
Guillaume Gardey,
Cyrille d'Haese,
Raik Nagel,
+Christopher Oezbek,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
Martin Kähmer,
Ervin Kolenovic,
Krzysztof A. Kościuszkiewicz,
+Christian Kopf,
Jeffrey Kuhn,
Alex Montgomery,
-Christopher Oezbek,
John Relph,
Moritz Ringler,
Andreas Rudert,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
+Ulrich Stärk,
Martin Stolle,
David Weitzman,
Seb Wills,
<p>
-</HTML>
+</body>
+</html>
<a href="CustomEntriesHelp.html">Customizing entry types</a><br>
<a href="GeneralFields.html">Customizing general fields</a><br>
<a href="EndNoteFilters.html">The EndNote import/export filter set</a><br>
- <a href="OpenOfficeHelp.html">Using JabRef bibliographies in OpenOffice.org</a><br>
<a href="EntryEditorHelp.html">Entry editor</a><br>
+ <a href="TimeStampHelp.html">Entry time stamps</a><br>
<a href="CiteSeerHelp.html">Fetching entries from <em>CiteSeer</em></a><br>
<a href="MedlineHelp.html">Fetching entries from <em>Medline</em></a><br>
<a href="IEEEXploreHelp.html">Fetching entries from <em>IEEExplore</em></a><br>
<a href="ContentSelectorHelp.html">Field content selector</a><br>
- <a href="JournalAbbreviations.html">Journal abbreviations</a><br>
<a href="GroupsHelp.html">Help on using <em>Groups</em></a><br>
+ <a href="ImportInspectionDialog.html">Import inspection window</a><br>
+ <a href="JournalAbbreviations.html">Journal abbreviations</a><br>
<a href="BaseFrameHelp.html">The JabRef main window</a><br>
- <a href="MarkingHelp.html">Marking entries</a><br>
<a href="OwnerHelp.html">The 'owner' field</a><br>
+ <a href="MarkingHelp.html">Marking entries</a><br>
+ <a href="OpenOfficeHelp.html">Using JabRef bibliographies in OpenOffice.org</a><br>
<a href="ExternalFiles.html">PDF/PS/URL/DOI links in JabRef</a><br>
<a href="SearchHelp.html">Searching in JabRef</a><br>
<a href="StringEditorHelp.html">String editor</a><br>
- <a href="TimeStampHelp.html">Entry time stamps</a><br>
- <a href="ImportInspectionDialog.html">Import inspection window</a><br>
-
-
-
-
-
-
-
-
-
+ <a href="PreviewHelp.html">Entry preview setup</a><br>
+ <a href="XMPHelp.html">XMP metadata support in JabRef</a>
</HTML>
<ul>
<li><code>HTMLChars</code> : replaces TeX-specific special characters (e.g. {\^a} or {\"{o}})
with their HTML representations.
+<li><code>HTMLParagraphs</code> : interprets two consecutive newlines (e.g. \n \n) as the beginning of a new paragraph and creates paragraph-html-tags accordingly.
<li><code>XMLChars</code> : replaces TeX-specific special characters (e.g. {\^a} or {\"{o}})
with their XML representations.
+
<li><code>CreateDocBookAuthors</code> : formats the author field in DocBook style.
+<li><code>CreateDocBookEditors</code> : to be documented.
+
<li><code>CurrentDate</code> : outputs the current date. With no argument, this formatter outputs the
current date and time in the format "yyyy.MM.dd hh:mm:ss z" (date, time and time zone). By giving a
different format string as argument, the date format can be customized. E.g.
<li><code>AuthorFirstFirst</code> : formats author/editor fields with the first names first.
<li><code>AuthorFirstFirstCommas</code> : formats author/editor fields with the first names first, and deliminated by commas.
+<li><code>AuthorFirstAbbrLastCommas</code> : to be documented.
+<li><code>AuthorFirstAbbrLastOxfordCommas</code> : to be documented.
+<li><code>AuthorFirstLastOxfordCommas </code> : to be documented.
+
<li><code>AuthorLastFirst</code> : formats author/editor fields with the last names first.
<li><code>AuthorLastFirstAbbreviator</code> : abbreviates first and middle names of all authors. This formatter requires AuthorLastFirst
to have been run earlier.
-<li><code>AuthorAndsReplacer</code> : replaces "and" between names with ";", and "&" between the last two.
+<li><code>AuthorLastFirstCommas</code> : to be documented.
+<li><code>AuthorLastFirstOxfordCommas</code> : to be documented.
+<li><code>AuthorLastFirstAbbrCommas</code> : to be documented.
+<li><code>AuthorLastFirstAbbrOxfordCommas</code> : to be documented.
+
+<li><code>AuthorAndsReplacer</code> : replaces "and" between names with ";", and "&" between the last two.
<li><code>AuthorAndsCommaReplacer</code> : replaces "and" between names with ",", and "&" between the last two.
+<li><code>AuthorOrgSci</code> : first author is in "last, first" all others in "first last". First names are abbreviated.
+<li><code>AuthorAbbreviator : to be documented.
+
+<li><code>NoSpaceBetweenAbbreviations</code> : spaces between multiple abbreviated first names are removed.
<li><code>FormatPagesForHTML</code> : replaces "--" with "-".
<li><code>FormatPagesForXML</code> : replaces "--" with an XML en-dash.
+
<li><code>RemoveBrackets</code> : removes all curly brackets "{" or "}".
+<li><code>RemoveBracketsAddComma</code> : to be documented.
+<li><code>RemoveWhitespace</code> : to be documented.
<li><code>RemoveLatexCommands</code> : removes LaTeX commands like <code>\em</code>, <code>\textbf</code>, etc. If
used together with <code>HTMLChars</code> or <code>XMLChars</code>, this formatter should be called last.
<li><code>ToLowerCase</code> : turns all characters into lower case.
+
+<li><code>CompositeFormat</code> : to be documented.
+<li><code>GetOpenOfficeType</code> : to be documented.
+<li><code>RTFChars</code> : to be documented.
+<li><code>ResolvePDF</code> : to be documented.
+
</ul>
<p>If none of the available formatters can do what you want to achieve, you can add your own by implementing
into the <code>net.sf.jabref.export.layout.format</code> package, you can call the formatter by its
class name only, like with the standard formatters. Otherwise, you must call the formatter by its fully
qualified name (including package name). In any case, the formatter must be in your classpath when running
- JabRef.
+ JabRef.</p>
+
+<a name="NameFormatter">
+<H2>Using Custom Name Formatters</H2>
+
+<p>With JabRef 2.2 it is now possible to define custom name formatters using the bibtex-sty-file syntax.
+This allows ultimate flexibility, but is a cumbersome to write</p>
+<p>You can define your own formatter in the preference tab "Name Formatter" using the following format
+and then use it with the name given to it as any other name formatter</p>
+
+<code>
+ <case1>@<range11>@<format>@<range12>@<format>@<range13>...@@<br>
+ <case2>@<range21>@... and so on.
+</code>
+
+<p>This format first splits the task to format a list of author into cases depending on
+how many authors there are (this is since some formats differ depending on how many authors there are).
+Each individual case is separated by @@ and contains instructions on how to format each author in the case.
+These instructions are separated by a @.</p>
+<p>Cases are identified using integers (1,2,3,etc.) or the character * (matches any number of authors) and will tell
+the formatter to apply the following instructions if there are a number of less or equal of authors given.
+</p>
+<p>
+ Ranges are either <code><integer>..<integer></code>, <code><integer></code> or the character <code>*</code> using a 1 based index for indexing
+ authors from the given list of authors. Integer indexes can be negative to denote them to start from
+ the end of the list where -1 is the last author.
+</p>
+
+<p>For instance with an authorlist of "Joe Doe and Mary Jane and Bruce Bar and Arthur Kay":</p>
+<ul>
+ <li> 1..3 will affect Joe, Mary and Bruce</li>
+ <li> 4..4 will affect Arthur </li>
+ <li> * will affect all of them</li>
+ <li> 2..-1 will affect Mary, Bruce and Arthur</li>
+</ul>
+
+<p>The <code><format></code>-strings use the Bibtex formatter format:</p>
+
+<p>
+ The four letter v, f, l, j indicate the name parts von, first, last, jr which
+ are used within curly braces. A single letter v, f, l, j indicates that the name should be abbreviated.
+ If one of these letters or letter pairs is encountered JabRef will output all the respective names
+ (possibly abbreviated), but the whole expression in curly braces is only printed if the name part exists.</p>
+
+<p>For instance if the format is "{ll} {vv {von Part}} {ff}" and the names are "Mary Kay and John von Neumann",
+ then JabRef will output "Kay Mary" (with two space between last and first) and "Neuman von von Part John".</p>
+
+<p>I give two examples but would rather point you to the bibtex documentation.</p>
+
+<p>Small example: <code>"{ll}, {f.}"</code> will turn <code>"Joe Doe"</code> into <code>"Doe, J."</code></p>
+
+<p>Large example:</p>
+<blockquote>
+<p> To turn: </p>
+<p><code>"Joe Doe and Mary Jane and Bruce Bar and Arthur Kay"</code></p>
+<p>into</p>
+<p><code>"Doe, J., Jane, M., Bar, B. and Kay, A."</code></p>
+<p>you would use</p>
+<p><code>1@*@{ll}, {f}.@@2@1@{ll}, {f}.@2@ and {ll}, {f}.@@*@1..-3@{ll}, {f}., @-2@{ll}, {f}.@-1@ and {ll}, {f}.</code></p>
+</blockquote>
+<p>If somebody would like to write a better tutorial about this: Write a mail to one of the JabRef mailinglists!</p>
<H3>Conditional output</H3>
your entries based on keyword. Now use the following commands to group by keyword:
<p><code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
-<br> \endgroup{keywords}</code>
+<br> \endgroup{keywords}</code>
<H2>Sharing your work</H2>
These directories will supersede the main directories.
</P>
-
-</HTML>
+<a name="RegularExpressionSearch">
+<H2>Using Regular Expression Search for Auto-Linking</H2>
+</a>
+<p>
+In the previous sections JabRef's auto-linking feature was described: If you choose names for your files
+corresponding to the bibtex-key + plus the extension, JabRef will automatically be able to find it.
+</p><p>
+Since JabRef 2.2 it is now possible to have greater flexibility in the naming scheme by using
+regular expression for the search. In most cases it should not be necessary though to adapt the given default.
+</p><p>
+If you open the external preferences
+(Options -> Preferences -> External Programs) you will find an option called "Use Regular Expression Search".
+Checking this option will allow you to enter your own regular expression for search in the PDF directories.
+</p><p>
+The following syntax is understood:
+</p>
+<ul>
+ <li><code>*</code> - Search in all immediate all subdirectories excluding the current
+ and any deeper subdirectories.</li>
+ <li><code>**</code> - Search in all subdirectories recursively AND the current directory.</li>
+ <li><code>.</code> and <code>..</code> - The current directory and the parent directory.</li>
+ <li><code>[title]</code> - All expressions in square brackets are replace by the corresponding field in the current
+ entry</li>
+ <li><code>[extension]</code> - Is replaced by the file-extension of the field you are using.</li>
+ <li>All other text is interpreted as a regular expression. But caution: You need to escape backslashes by putting
+ two backslashes after each other to not confuse them with the path-separator.</li>
+</ul>
+<p>
+The default for searches is <code>**/.*[bibtexkey].*\\.[extension]</code>. As you can see this will
+search in all subdirectories of the extension-based directory (for instance in the PDF directory) for any file that has the correct extension and
+contains the Bibtex-key somewhere.
+</p>
+</body>
+</html>
The entry preview is created using the same mechanism as used by the
<a href="CustomExports.html">Custom export filter</a> facility. When previewed,
an entry is processed using one of the two alternative layouts (you can switch between
-the two layouts by pressing CTRL-F9) to produce HTML code which is displayed by the
+the two layouts by pressing F9) to produce HTML code which is displayed by the
preview panel.
To modify the appearance and contents of the preview you need to edit the preview layouts
<H2>Normal</H2>
-In a normal search, the program searches your database for all occurences of your
-search string, once you press ENTER. All entries that don't match are hidden, leaving for display the matching entries only (filter mode), or are grayed-out (float mode).
+In a normal search, the program searches your database for all occurences of the words in your
+search string, once you press ENTER. Only entries containing all words will be considered matches.
+To search for sequences of words, enclose the sequences in double quotes. For instance, the query
+<b>progress "marine aquaculture"</b> will match entries containing both the word "progress" and the
+phrase "marine aquaculture". All entries that don't match are hidden, leaving for display the
+matching entries only (filter mode), or are grayed-out (float mode).
To stop displaying the search results, press ESC or click "Clear search".
<a name="advanced"><H2>Field specification, logical operators</H2>
--- /dev/null
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>XMP metadata support in JabRef</H1>
+<p>
+XMP is a standard created by Adobe Systems for storing metadata (data about data) in files.
+An well known example for metadata are MP3 tags, which can be used to describe artist, album and song name
+of a MP3 file. Adding metadata to MP3 helps other people to identify the songs correctly independent of file-name
+and can provide means for software (MP3 players for instance) to sort and group songs.
+</p>
+<p>
+With XMP-support the JabRef team tries to bring the advantages of metadata to the world of reference managers.
+You can now choose to "Write XMP" metadata in the General Tab of JabRef, which will put all the Bibtex information
+into the PDF. If you then email this PDF to a collegue she can just drag the file into JabRef and all information
+that you entered will be available to her.
+</p>
+
+<H2>Usage</H2>
+
+To use the XMP-feature in JabRef you can do the following:
+
+<ul>
+ <li>To <b>import a single annotated PDF-file</b> that contains XMP you can select "File -> Import into... -> XMP-annotated PDF" or drag the file into the main view.</li>
+ <li>To <b>write the bibliographic information to the associated PDF</b> do the following: Double click the entry in the main view, go to the "General" tab and click on "Write XMP".</li>
+ <li>If you want <b>to annotate all the PDFs in a given database</b> you can select "Tools -> Write XMP for database"</li>
+ <li>To verify if it worked you can open the PDF in Adobe Acrobat and select
+ "File -> Document Properties -> Additional Metadata -> Advanced". In the tree to the right you should see an entry called "http://purl.org/net/bibteXMP"
+<ul>
+
+<h2>BibteXmp Fileformat</h2>
+
+<p>
+XMP uses a subset of the Resource Description Framework (RDF) to store data. For JabRef a new metadata
+format is used which maps very closely to BibTeX. Basically all fields and values are turned into
+nodes of an XML document. Only authors and editors are stored as rdf:Seq-structures, so users
+of the data can skip the splitting on 'and's. All strings and crossrefs will be resolved in the data.
+</p>
+<p>
+The following easy minimal schema is used:
+</p>
+<p>
+<ul>
+ <li>The BibTeX-key is stored as <code>bibtexkey</code>.</li>
+ <li>The type of the BibTeX-entry is stored as <code>entrytype</code>.</li>
+ <li><code>author</code> and <code>editor</code> are encoding as <code>rdf:Seq</code>s where the
+ individual authors are represented as <code>rdf:li</code>s.</li>
+ <li>All other fields are saved using their field-name as is.</li>
+</ul>
+</p>
+<p>
+The following is an example of the mapping
+</p>
+<pre>
+@INPROCEEDINGS{CroAnnHow05,
+ author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},
+ title = {Effective work practices for floss development: A model and propositions},
+ booktitle = {Hawaii International Conference On System Sciences (HICSS)},
+ year = {2005},
+ owner = {oezbek},
+ timestamp = {2006.05.29},
+ url = {http://james.howison.name/publications.html}
+}
+</pre>
+
+will be transformed into
+
+<pre>
+<rdf:Description xmlns:bibtex="http://jabref.sourceforge.net/bibteXMP/"
+ bibtex:bibtexkey="CroAnnHow05"
+ bibtex:year="2005"
+ bibtex:title="Effective work practices for floss development: A model and propositions"
+ bibtex:owner="oezbek"
+ bibtex:url="http://james.howison.name/publications.html"
+ bibtex:booktitle="Hawaii International Conference On System Sciences (HICSS)"
+ bibtex:timestamp="2006.05.29">
+ <bibtex:author>
+ <rdf:Seq>
+ <rdf:li>K. Crowston</rdf:li>
+ <rdf:li>H. Annabi</rdf:li>
+ <rdf:li>J. Howison</rdf:li>
+ <rdf:li>C. Masango</rdf:li>
+ </rdf:Seq>
+ </bibtex:author>
+ <bibtex:entrytype>Inproceedings</bibtex:entrytype>
+</rdf:Description>
+</pre></td></tr>
+</table>
+
+<p>
+Beware of the following caveats if you trying to parse bibteXMP:
+</p>
+<p>
+<ul>
+ <li>In RDF attribute-value pairs can also be expressed as nodes and vice versa.</li>
+</ul>
+</p>
+<H2>Related Links:</H2>
+<p>
+Some links about XMP and annotating PDFs:
+</p>
+<p>
+<ul>
+ <li><a href="http://freelancepropaganda.com/themp/">James Howison's blog "Themp---Managing Academic Papers like MP3s"</a></li>
+ <li><a href="http://www.xml.com/pub/a/2004/09/22/xmp.html">XML.com article about XMP</a></li>
+ <li><a href="http://jempbox.org">JempBox</a> and <a href="http://pdfbox.org">PDFBox</a> by Ben Litchfield are the Jaba libraries
+ used to access the PDFs and the metadata stream.</a></li>
+ <li><a href="http://episteme.arstechnica.com/eve/ubb.x/a/tpc/f/8300945231/m/377001889631">Good thread on ArsTechnica discussing the management of PDFs.</a></li>
+ <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/xmpspecification.pdf">Adobe XMP Specification</a></li>
+</ul>
+</p>
+</body>
+</HTML>
\ No newline at end of file
Guillaume Gardey
Cyrille d'Haese
Raik Nagel
+Christopher Oezbek
Ellen Reitmayr
Michael Spiegel
Ulrik Stervbo
Sascha Hunold
Bernd Kalbfuss
Martin Kähmer
+Christian Kopf
Alex Montgomery
John Relph
Moritz Ringler
Rudolf Seemann
Mike Smoot
+Ulrich Stärk
Martin Stolle
David Weitzman
Seb Wills
Cyrille d'Haese,
Raik Nagel,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
Christopher Oezbek,
John Relph,
Moritz Ringler,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
<H1>Eintragsvorschau einstellen</H1>
-Die Eintragsvorschau wird mit denselben Mechanismen erstellt, die auch bei den <a href="CustomExports.html">Exportfiltern</a> angewendet werden. Bei der Vorschau durchläuft ein Eintrag eins von zwei möglichen Layouts (die sie mit STRG-F9 wechseln können) und erstellt HTML-Code, der im Vorschaudialog angezeigt wird.
+Die Eintragsvorschau wird mit denselben Mechanismen erstellt, die auch bei den <a href="CustomExports.html">Exportfiltern</a> angewendet werden. Bei der Vorschau durchläuft ein Eintrag eins von zwei möglichen Layouts (die sie mit F9 wechseln können) und erstellt HTML-Code, der im Vorschaudialog angezeigt wird.
Aussehen und Inhalt der Vorschau können mit derselben Syntax verändert werden, die in der Hilfe zur Anpassung der <a href="CustomExports.html">Exportfilter</a> beschrieben wird.
Cyrille d'Haese,
Raik Nagel,
Ellen Reitmayr,
+Gert Renckens,
Andreas Rudert,
Michael Spiegel,
Ulrik Stervbo,
Christopher Oezbek,
John Relph,
Moritz Ringler,
+Mark Schenk,
Rudolf Seemann,
Toralf Senger,
Mike Smoot,
<li>Vous décidez des champs affichés dans ce tableau en cochant les
champs que vous voulez voir dans la fenêtre de dialogue <strong>Préférences</strong>.</li>
<li>Pour éditér la valeur d'un champ, double-cliquez sur la ligne que vous voulez modifiez. Vous pouvez naviguer dans le tableau en utilisant les flèches du clavier.</li>
-<li>Le tableau est trié selon une série de champs de votre choix. L'ordre de tri par défaut est configuré dans <strong>Options -> Préférences -> Table des entrées</strong> mais vous pouvez changer rapidement et simplement cet ordre en double-cliquant sur le titre d'une colonne pour définir le critère de tri principal et en simple-cliquant sur le titre pour ajouter un nouveau sous-critère de tri. Si vous cliquez sur le titre d'une colonne qui est déjà sélectionnée comme critère de tri, le sens de tri est inversé.
+<li>Le tableau est trié selon une série de champs de votre choix.
+L'ordre de tri par défaut est configuré dans <strong>Options -> Préférences -> Table des entrées</strong>
+mais pour changer rapidement cet ordre,
+ cliquez l'entête d'une colonne pour la définir comme critère de tri principal, ou
+ inverser l'ordre du tri s'il est déjà défini. Un clic supplémentaire désélectionnera la colonne
+ comme critère de tri. Maintenez la touche <b>CONTROL</b> enfoncée et cliquez sur un autre entête de colonne pour l'ajouter, l'inverser
+ ou l'enlever comme critère de tri auxiliaire. Vous pouvez ajouter un nombre arbitraire
+ de critères auxiliaires.
<li>Vous pouvez ajuster la largeur des colonnes en faisant glisser les limites
entre les entêtes.</li>
<li>Dans la fenêtre de dialogue <strong>Préférences</strong>, choisissez si le tableau
<H2>Editer une entrée</H2> Pour ouvrir la <a
href="EntryEditorHelp.html">fenêtre d'édition</a> sur une entrée existante,
-double-cliquez simplement sur la ligne correspondant à l'entrée (ou appuyez sur ENTREE après avoir sélectionner l'entrée).
+double-cliquez simplement sur la ligne correspondant à l'entrée (ou appuyez sur ENTREE après avoir sélectionner l'entrée).
<H2>Référencer une chaîne <em>BibTeX</em> dans un champ</H2>
Dans JabRef vous écrivez le contenu de tous les champs de la même
<a href="CustomEntriesHelp.html">Personnalisation des types d'entrées</a><br>
<a href="GeneralFields.html">Personnalisation des champs généraux</a><br>
<a href="EndNoteFilters.html">Filtres d'importation/exportation d'EndNote</a><br>
- <a href="OpenOfficeHelp.html">Utiliser les bibliographies JabRef dans OpenOffice.org</a><br>
<a href="EntryEditorHelp.html">Éditeur d'entrées</a><br>
+ <a href="TimeStampHelp.html">Horodatage des entrées</a><br>
<a href="CiteSeerHelp.html">Récupération des entrées depuis <em>CiteSeer</em></a><br>
<a href="MedlineHelp.html">Récupération des entrées depuis <em>Medline</em></a><br>
<a href="IEEEXploreHelp.html">Récupération des entrées depuis <em>IEEExplore</em></a><br>
<a href="ContentSelectorHelp.html">Sélecteur de contenu de champ</a><br>
- <a href="JournalAbbreviations.html">Abréviations de journaux</a><br>
<a href="GroupsHelp.html">Utilisation des <em>Groupes</em></a><br>
+ <a href="ImportInspectionDialog.html">Fenêtre de vérification des importations</a><br>
+ <a href="JournalAbbreviations.html">Abréviations de journaux</a><br>
<a href="BaseFrameHelp.html">La fenêtre principale de JabRef</a><br>
- <a href="MarkingHelp.html">Étiqueter des entrées</a><br>
<a href="OwnerHelp.html">Le champ 'owner' (propriétaire)</a><br>
+ <a href="MarkingHelp.html">Étiqueter des entrées</a><br>
+ <a href="OpenOfficeHelp.html">Utiliser les bibliographies JabRef dans OpenOffice.org</a><br>
<a href="ExternalFiles.html">Liens PDF/PS/URL/DOI dans JabRef</a><br>
<a href="SearchHelp.html">Recherche dans JabRef</a><br>
<a href="StringEditorHelp.html">Éditeur de chaînes</a><br>
- <a href="TimeStampHelp.html">Horodatage des entrées</a><br>
- <a href="ImportInspectionDialog.html">Fenêtre de vérification des importations</a><br>
<a href="PreviewHelp.html">Configuration de l'aperçu des entrées</a><br>
+ <a href="XMPHelp.html">Support des metadonnées XMP dans JabRef</a>
</p>
<p>
-Dans notre exemple de fichier d'exportation, cela pourrait ressembler à
+Dans notre exemple de fichier d'exportation, cela pourrait ressembler à
</p>
<p>
</p>
<p>
-Vous pouvez aussi indiquer plusieurs formateurs séparés par des virgules. Ils seront alors appelés séquentiellement de la gauche vers la droite, par exemple :
+Vous pouvez aussi indiquer plusieurs formateurs séparés par des virgules. Ils seront alors appelés séquentiellement de la gauche vers la droite, par exemple :
</p>
<p>
<code>\format[ToLowerCase,HTMLChars]{\author}</code>
<li><code>HTMLChars</code> : remplace les caractères spéciaux spécifiques à TeX (par exemple : {\^a} ou {\"{o}}) par leur représentation HTML.
<li><code>XMLChars</code> : remplace les caractères spéciaux spécifiques à TeX (par exemple : {\^a} ou {\"{o}}) par leur représentation XML.
<li><code>CreateDocBookAuthors</code> : formate le contenu du champ author selon le style DocBook.
-<li><code>CurrentDate</code> : renvoie la date actuelle. Sans argument, ce formateur renvoie la date et l'heure actuelle au format "yyyy.MM.dd hh:mm:ss z" (date, heure et fuseau horaire). En donnant une chaîne de format différent comme argument, le format de la date peut-être adapté. Par exemple,
+<li><code>CurrentDate</code> : renvoie la date actuelle. Sans argument, ce formateur renvoie la date et l'heure actuelle au format "yyyy.MM.dd hh:mm:ss z" (date, heure et fuseau horaire). En donnant une chaîne de format différent comme argument, le format de la date peut-être adapté. Par exemple,
<code>\format[CurrentDate]{yyyy.MM.dd}</code> renverra uniquement la date, comme par exemple 2005.11.30.
<li><code>AuthorFirstFirst</code> : formate le contenu des champs author/editor en mettant les prénoms en premier.
<li><code>AuthorFirstFirstCommas</code> : formate le contenu des champs author/editor en mettant les prénoms en premier et des virgules comme séparateurs.
<li><code>AuthorLastFirst</code> : formate le contenu des champs author/editor en mettant le nom de famille en premier.
<li><code>AuthorLastFirstAbbreviator</code> : réduit les prénoms de tous les auteurs à leurs initiales. Ce formateur nécessite d'avoir préalablement utilisé AuthorLastFirst.
-<li><code>AuthorAndsReplacer</code> : remplace "and" par ";" entre les premiers noms et par "&" entre les deux derniers.
-<li><code>AuthorAndsCommaReplacer</code> : remplace "and" entre les noms par une virgule (",") et "&" entre les deux derniers.
+<li><code>AuthorAndsReplacer</code> : remplace "and" par ";" entre les premiers noms et par "&" entre les deux derniers.
+<li><code>AuthorAndsCommaReplacer</code> : remplace "and" entre les noms par une virgule (",") et "&" entre les deux derniers.
+<li><code>AuthorOrgSci</code> : premier auteur selon "nom, prénom" et tous les autres selon "prénom nom". Les prénoms sont abrégés.
<li><code>FormatPagesForHTML</code> : remplace "--" par "-".
<li><code>FormatPagesForXML</code> : remplace "--" par un tiret XML.
<li><code>RemoveBrackets</code> : supprime toutes les accolades "{" ou "}".
</p>
<p>
<code>\begingroup{keywords}New Category: \format[HTMLChars]{\keywords}
-<br> \endgroup{keywords}</code>
+<br> \endgroup{keywords}</code>
</p>
<h2>Partage de votre travail </h2>
Ces répertoires remplacent alors les répertoires principaux.
</P>
-
-</HTML>
+<a name="RegularExpressionSearch">
+<H2>Utiliser la recherche d'expressions régulières pour les liaisons automatiques</H2>
+</a>
+<p>
+Dans les sections précédentes, la fonction de liaison automatique de JabRef était décrite : si vous
+choisissiez des noms de fichiers qui correspondaient à la clef BibTex suivi de l'extension,
+JabRef était capable de trouver les fichiers automatiquement.
+
+</p><p>
+A partir de JabRef 2.2, il est possible d'avoir une plus grande flexibilité dans la forme du nom grâce à l'utilisation
+d'une expression régulière pour la recherche. Dans la plupart des cas, adapter l'expression régulière donnée par défaut devrait suffire.
+
+</p><p>
+Si vous ouvrez les préférences pour les programmes externes (Options -> Préférences -> Programmes externes),
+vous y trouverez une option nommée "Rechercher l'expression régulière".
+Cocher cette option vous permettra d'entrer votre propre expression régulière pour la recherche dans les
+répertoires PDF.
+
+</p><p>
+Voici la syntaxe à utiliser :
+</p>
+<ul>
+ <li><code>*</code> - Rechercher dans tous les sous-répertoires directs en excluant le répertoire courant
+ et tout autre sous-répertoire.</li>
+ <li><code>**</code> - Rechercher récursivement dans tous les sous-répertoires ET dans le répertoire courant.</li>
+ <li><code>.</code> et <code>..</code> - Le répertoire courant et le répertoire parent.</li>
+ <li><code>[title]</code> - Toutes les expressions entre crochets sont remplacées par le champ correspondant dans l'entrée courante.</li>
+ <li><code>[extension]</code> - Remplacement par l'extension de fichier du champ que vous utilisez.</li>
+ <li>Tout autre texte est interprété comme une expression régulière. Mais attention : vous devez remplacer
+ chaque caractère anti-slash (\) par deux anti-slashs (\\) afin d'éviter la confusion avec un séparateur de répertoire .</li>
+</ul>
+<p>
+Par défaut, l'expression régulière de recherche est <code>**/.*[bibtexkey].*\\.[extension]</code>. Comme vous pouvez le voir cela effectuera
+la recherche dans tous les sous-répertoires du répertoire défini pour l'extension (par exemple dans le répertoire PDF) de tout nom de fichier qui possède la bonne extension et
+qui contient quelque part la clef BibTeX.
+
+
+
+
+
+</p>
+</body>
+</html>
L'aperçu des entrées est créé en utilisant le même mécanisme que pour les
<a href="CustomExports.html">filtres d'exportation personnalisés</a>.
En mode aperçu, une entrée est traitée en utilisant l'une des deux mises en page disponibles
-(vous pouvez basculer entre les deux mises en page en pressant CTRL-F9) afin de produire du code HTML qui est affiché dans le panneau d'aperçu.
+(vous pouvez basculer entre les deux mises en page en pressant F9) afin de produire du code HTML qui est affiché dans le panneau d'aperçu.
-Pour modifier l'apparence et le contenu de l'aperçu vous devez éditer les mises en page de l'aperçu en utilisant la
+Pour modifier l'apparence et le contenu de l'aperçu vous devez éditer les mises en page de l'aperçu en utilisant la
syntaxe décrite dans le fichier d'aide portant sur les
<a href="CustomExports.html">filtres d'exportation personnalisés</a>.
--- /dev/null
+<HTML>
+
+<BODY text="#275856">
+<basefont size="4" color="#2F4958" face="arial">
+
+<H1>Support des metadonnées XMP dans JabRef</H1>
+
+NdT : Menus à vérifier !!!
+
+<p>
+XMP est un standard créé par Adobe Systems pour stocker des métadonnées (des données sur les données) dans des fichiers.
+A exemple bien connu de métadonnées sont les balises MP3 qui peuvent être utilisées pour décrire l'artiste, l'album et le nom de la chanson
+dans un fichier MP3. Ajouter des métadonnées à des fichiers MP3 aide les autres utilisateurs à identifier correctement les chansons indépendamment du nom du fichier
+et permet aux logiciels (lecteurs MP3 par exemple) de trier et de grouper les chansons.
+</p>
+<p>
+Avec le support de XMP, l'équipe de développement de JabRef introduit les avantages des métadonnées au monde des gestionnaires de références.
+Vous avez maintenant la possibilité d'"écrire des métadonnées XMP" dans l'onglet General de Jabref, ce qui mettra toutes les informations BibTex dans un fichier PDF. En transférant ce fichier à un collègue, il aura simplement à faire glisser le fichier dans JabRef pour que toutes les informations que vous y avez entrées lui soient disponibles.
+</p>
+
+<H2>Utilisation</H2>
+
+Pour utiliser la fonction XMP dans JabRef, vous pouvez faire les choses suivantes :
+
+<ul>
+ <li><b>Importer un unique fichier PDF annoté</b> contenant les métadonnées XMP. Vous pouvez sélectionner "Fichier -> Importer dans... -> PDF avec annotations XMP" ou faire glisser le fichier dans la fenêtre principale.</li>
+ <li><b>Ecrire les informations bibliographiques dans le fichier PDF associé.</b> Pour cela, double-cliquez sur l'entrée dans
+ la fenêtre principale, allez dans l'onglet "General" et cliquer sur "Ecrire XMP".</li>
+ <li>Si vous voulez <b>annoter tous les PDFs dans une base de données déterminée</b> vous pouvez sélectionner "Outils -> Ecrire XMP pour la base de données"</li>
+ <li>Pour vérifier si cela a fonctionné, vous pouvez ouvrir le PDF dans Adobe Acrobat et sélectionner
+ "Fichier -> Propriétés du Document -> Métadonnées additionnelles -> Avancé". Dans l'arborescence sur la droite vous devriez voir une entrée nommée "http://purl.org/net/bibteXMP".
+</ul>
+
+<h2>Format de fichier BibteXmp</h2>
+
+<p>
+XMP utilise un sous-ensemble du Schéma de Description des Ressources (Resource Description Framework - RDF) pour stocker les données. Pour JabRef, un nouveau format de métadonnées
+est utilisé ; il ressemble beaucoup au format BibTeX. Fondamentalement, tous les champs et valeurs sont transformés en
+noeuds dans un document XML. Seuls les auteurs et les éditeurs sont stockés comme des rdf:Seq-structures, aussi les utilisateurs
+des données peuvent éviter la séparation basées sur des 'and'. Toutes les chaînes et les références croisées seront présentes dans les données.
+</p>
+<p>
+Le schéma suivant, facile et minimal, est utilisé :
+</p>
+<p>
+<ul>
+ <li>La clef BibTeX est stockée comme une <code>bibtexkey</code>.</li>
+ <li>Le type d'entrée BibTeX est stocké comme une <code>entrytype</code>.</li>
+ <li>les champs <code>author</code> et <code>editor</code> sont encodés comme des <code>rdf:Seq</code>s où les auteurs individuels sont représentés par des <code>rdf:li</code>s.</li>
+ <li>Tous les autres champs sont sauvés en utilisant directement le nom de leur champ.</li>
+</ul>
+</p>
+<p>
+Ci-dessous, un exemple de mise en correspondance
+</p>
+<pre>
+@INPROCEEDINGS{CroAnnHow05,
+ author = {Crowston, K. and Annabi, H. and Howison, J. and Masango, C.},
+ title = {Effective work practices for floss development: A model and propositions},
+ booktitle = {Hawaii International Conference On System Sciences (HICSS)},
+ year = {2005},
+ owner = {oezbek},
+ timestamp = {2006.05.29},
+ url = {http://james.howison.name/publications.html}
+}
+</pre>
+
+sera transformé en
+<pre>
+<rdf:Description xmlns:bibtex="http://jabref.sourceforge.net/bibteXMP/"
+ bibtex:bibtexkey="CroAnnHow05"
+ bibtex:year="2005"
+ bibtex:title="Effective work practices for floss development: A model and propositions"
+ bibtex:owner="oezbek"
+ bibtex:url="http://james.howison.name/publications.html"
+ bibtex:booktitle="Hawaii International Conference On System Sciences (HICSS)"
+ bibtex:timestamp="2006.05.29">
+ <bibtex:author>
+ <rdf:Seq>
+ <rdf:li>K. Crowston</rdf:li>
+ <rdf:li>H. Annabi</rdf:li>
+ <rdf:li>J. Howison</rdf:li>
+ <rdf:li>C. Masango</rdf:li>
+ </rdf:Seq>
+ </bibtex:author>
+ <bibtex:entrytype>Inproceedings</bibtex:entrytype>
+</rdf:Description>
+</pre></td></tr>
+</table>
+
+<p>
+Faites attention aux pièges suivants si vous essayer de traiter les métadonnées bibtexXMP :
+</p>
+<p>
+<ul>
+ <li>Selon RDF, les couples attribut-valeur peuvent aussi être exprimés comme des noeuds, et vice-versa.</li>
+</ul>
+</p>
+<H2>Liens :</H2>
+<p>
+Quelques liens (en anglais) à propos de XMP et de l'annotation des PDFs :
+</p>
+<p>
+<ul>
+ <li><a href="http://freelancepropaganda.com/themp/">James Howison's blog "Themp---Managing Academic Papers like MP3s"</a></li>
+ <li><a href="http://www.xml.com/pub/a/2004/09/22/xmp.html">XML.com article about XMP</a></li>
+ <li><a href="http://jempbox.org">JempBox</a> and <a href="http://pdfbox.org">PDFBox</a> by Ben Litchfield are the Jaba libraries
+ used to access the PDFs and the metadata stream.</a></li>
+ <li><a href="http://episteme.arstechnica.com/eve/ubb.x/a/tpc/f/8300945231/m/377001889631">Good thread on ArsTechnica discussing the management of PDFs.</a></li>
+ <li><a href="http://partners.adobe.com/public/developer/en/xmp/sdk/xmpspecification.pdf">Adobe XMP Specification</a></li>
+</ul>
+</p>
+</body>
+</HTML>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="744.09448819"
- height="1052.3622047"
- id="svg2"
- sodipodi:version="0.32"
- inkscape:version="0.44"
- sodipodi:docbase="/home/alver/Documents"
- sodipodi:docname="jabrefIkon.svg">
- <defs
- id="defs4">
- <linearGradient
- id="linearGradient2915">
- <stop
- id="stop2917"
- offset="0"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- id="stop2919"
- offset="1"
- style="stop-color:#dadce0;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient2909">
- <stop
- id="stop2911"
- offset="0"
- style="stop-color:white;stop-opacity:1;" />
- <stop
- id="stop2913"
- offset="1"
- style="stop-color:#cfd1d7;stop-opacity:1;" />
- </linearGradient>
- <linearGradient
- id="linearGradient2897">
- <stop
- style="stop-color:#dadee7;stop-opacity:1;"
- offset="0"
- id="stop2899" />
- <stop
- style="stop-color:#1e68c6;stop-opacity:1;"
- offset="1"
- id="stop2901" />
- </linearGradient>
- <linearGradient
- id="linearGradient2889">
- <stop
- style="stop-color:#e0e4ee;stop-opacity:1;"
- offset="0"
- id="stop2891" />
- <stop
- style="stop-color:#e0e4ee;stop-opacity:0;"
- offset="1"
- id="stop2893" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient2971"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.115225,0,0,1,-1.889007,46.1244)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient2974"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(1.082601,0,0,1,-1.374219,40)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient2983"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(8.119652e-2,0,0,7.966468e-2,422.1323,954.272)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient2985"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(8.119652e-2,0,0,7.966468e-2,424.2434,954.7598)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2909"
- id="linearGradient3878"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.824753e-2,0,0,3.538487e-2,403.2956,1005.814)"
- x1="145.45497"
- y1="332.74286"
- x2="326.12537"
- y2="576.18854" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient2915"
- id="linearGradient3880"
- gradientUnits="userSpaceOnUse"
- gradientTransform="matrix(3.863231e-2,4.140938e-3,-3.672702e-3,3.351102e-2,404.9189,1005.265)"
- x1="329.18756"
- y1="289.87192"
- x2="598.66205"
- y2="548.62866" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#666666"
- borderopacity="1.0"
- gridtolerance="50"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="21.286454"
- inkscape:cx="416.46054"
- inkscape:cy="31.511436"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- showgrid="false"
- inkscape:guide-bbox="false"
- showguides="true"
- inkscape:window-width="1118"
- inkscape:window-height="944"
- inkscape:window-x="0"
- inkscape:window-y="0" />
- <metadata
- id="metadata7">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1">
- <rect
- style="opacity:1;fill:#4f5f8f;fill-opacity:1"
- id="rect2905"
- width="716.55713"
- height="730.3371"
- x="10.717734"
- y="89.297173" />
- <path
- style="fill:url(#linearGradient2974);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 122.04224,150.95548 C 208.65029,150.95548 286.97046,184.73542 286.97046,184.73542 C 286.97046,184.73542 372.48612,237.27117 327.52453,611.24332 C 314.57556,683.68157 250.81542,747.98797 172.90939,747.98797 C 95.003363,747.98797 50.24884,702.05483 50.24884,648.46615 C 119.867,694.3993 168.69957,681.54848 189.48514,672.96384 C 199.45516,668.84613 251.63441,636.1731 257.44572,548.94433 C 264.07602,449.42251 247.50026,297.84312 122.04224,150.95548 z "
- id="path1972"
- sodipodi:nodetypes="cccscssc" />
- <path
- style="fill:url(#linearGradient2971);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.05348015px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 322.49657,164.88378 C 533.15821,196.83799 712.94701,311.87314 516.81377,452.47165 C 462.33232,497.20754 627.59274,671.35798 692.97048,751.2435 C 544.0545,717.69157 402.40271,580.28849 400.58666,476.43731 C 398.77062,401.34492 516.81377,393.35637 516.81377,347.02276 C 516.81377,300.68916 344.28916,262.34411 322.49657,164.88378 z "
- id="path1993"
- sodipodi:nodetypes="cccc" />
- <rect
- style="opacity:1;fill:#4f5f8f;fill-opacity:1"
- id="rect3872"
- width="24.96747"
- height="24.892717"
- x="403.74191"
- y="1008.134"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png" />
- <path
- style="fill:url(#linearGradient3878);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 407.84626,1010.4236 C 410.90607,1010.4236 413.43489,1010.4972 413.43489,1010.4972 C 413.43489,1010.4972 416.50376,1012.7951 414.91528,1026.0281 C 414.45779,1028.5913 412.2052,1030.8669 409.45284,1030.8669 C 406.70046,1030.8669 405.11931,1029.2413 405.11931,1027.3453 C 407.95995,1028.6292 410.06622,1027.9794 410.80057,1027.6755 C 411.15281,1027.5298 412.46165,1026.9172 412.43944,1023.8236 C 412.38788,1016.6442 413.08837,1015.0847 407.84626,1010.4236 z "
- id="path3874"
- sodipodi:nodetypes="cccscssc"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03" />
- <path
- style="fill:url(#linearGradient3880);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.05348015px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
- d="M 415.71976,1010.449 C 423.13477,1010.8154 428.70544,1016.8245 421.39485,1020.8079 C 419.34326,1022.1048 424.42839,1028.5544 426.39975,1031.4741 C 421.3644,1029.7968 416.96212,1024.6664 417.28063,1021.1794 C 417.49352,1018.6562 421.61195,1018.8269 421.78212,1017.2742 C 421.95228,1015.7216 419.07637,1015.8865 415.71976,1010.449 z "
- id="path3876"
- sodipodi:nodetypes="ccccsc"
- inkscape:export-filename="/home/alver/div/smalltheme/jabrefIkon-48.png"
- inkscape:export-xdpi="173.03"
- inkscape:export-ydpi="173.03" />
- </g>
-</svg>
+++ /dev/null
-#jabrefIcon=JabRef-icon.png
-jabrefIcon=ikon.gif
-about=JabRef-icon.png
-
-new=filenew.png
-open=fileopen.png
-loadSession=fileimport.png
-save=filesave.png
-saveAs=filesaveas.png
-copy=editcopy.png
-paste=editpaste.png
-cut=editcut.png
-undo=undo.png
-redo=redo.png
-refresh=reload.png
-left=1leftarrow.png
-right=1rightarrow.png
-up=1uparrow.png
-down=1downarrow.png
-add=edit_add.png
-remove=edit_remove.png
-delete=trash.png
-edit=edit.png
-help=help.png
-helpSmall=help.png
-helpContents=contents2.png
-search=search.png
-incSearch=search.png
-toggleSearch=search.png
-complete=button_ok.png
-wrong=cancel.png
-makeKey=wizard.png
-psSmall=ps.png
-pdfSmall=pdf-document.png
-openFile=pdf-document.png
-preferences=advancedsettings.png
-openUrl=agt_internet.png
-www=agt_internet.png
-wwwSmall=agt_internet_small.png
-medline=agt_internet.png
-integrityWarn=status_unknown.png
-integrityInfo=documentinfo.png
-integrityFail=gg_ignored.png
-
-togglePreview=text_bottom.png
-toggleGroups=queue.png
-editPreamble=preamble.png
-editStrings=strings.png
-emacs=emacs.png
-lyx=lyx2.png
-winedt=winedt.png
-required=reqIcon.png
-optional=optIcon.png
-general=genIcon.png
-abstract=absIcon.png
-source=viewsource.gif
-duplicate=duplicate.png
-autoGroup=run.png
-markEntries=mark.png
-unmarkEntries=unmark.png
-citeseer=wwwciteseer.png
-doiSmall=doismall.png
-groupsHighlightAny=groupsHighlightAny.png
-groupsHighlightAll=groupsHighlightAll.png
-close=fileclose.png
-close2=fileclose2.png
-integrityCheck=integrity.png
-groupIncluding=groupIncluding.png
-groupRefining=groupRefining.png
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- sodipodi:docname="splash-2.1.svg"
- sodipodi:docbase="/home/alver/jabref/src/images"
- inkscape:version="0.42+0.43pre1"
- sodipodi:version="0.32"
- id="svg2138"
- height="1052.3622047"
- width="744.09448819">
- <defs
- id="defs2140">
- <pattern
- patternTransform="translate(316.0000,1046.362)"
- id="pattern9054"
- xlink:href="#pattern9048"
- inkscape:collect="always" />
- <linearGradient
- id="linearGradient5361"
- inkscape:collect="always">
- <stop
- id="stop5363"
- offset="0"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- id="stop5365"
- offset="1"
- style="stop-color:#000000;stop-opacity:0;" />
- </linearGradient>
- <marker
- style="overflow:visible;"
- id="Arrow2Send"
- refX="0.0"
- refY="0.0"
- orient="auto"
- inkscape:stockid="Arrow2Send">
- <path
- transform="scale(0.3) rotate(180) translate(-5,0)"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- id="path3046"
- sodipodi:nodetypes="cccc" />
- </marker>
- <linearGradient
- gradientUnits="userSpaceOnUse"
- y2="300.91277"
- x2="491.20592"
- y1="300.91277"
- x1="445.01770"
- id="linearGradient5367"
- xlink:href="#linearGradient5361"
- inkscape:collect="always" />
- <pattern
- id="pattern9048"
- patternTransform="translate(231.0000,284.3622)"
- height="428.00000"
- width="572.00000"
- patternUnits="userSpaceOnUse">
- <image
- transform="translate(-231.0000,-284.3622)"
- style="opacity:1.0000000;stroke:#000000;stroke-width:5.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash4.png"
- y="284.36218"
- x="231.00000"
- xlink:href="behandlet.png"
- sodipodi:absref="/home/alver/Desktop/bilder/jabref/behandlet.png"
- width="572.00000"
- height="428.00000"
- id="image9050" />
- </pattern>
- </defs>
- <sodipodi:namedview
- inkscape:window-y="53"
- inkscape:window-x="15"
- inkscape:window-height="856"
- inkscape:window-width="750"
- inkscape:current-layer="layer1"
- inkscape:document-units="px"
- inkscape:cy="698.1925"
- inkscape:cx="364.52617"
- inkscape:zoom="1"
- inkscape:pageshadow="2"
- inkscape:pageopacity="0.0"
- borderopacity="1.0"
- bordercolor="#666666"
- pagecolor="#ffffff"
- id="base" />
- <metadata
- id="metadata2143">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="Layer 1">
- <rect
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- y="170.36218"
- x="77.500000"
- height="432.00000"
- width="576.00000"
- id="rect6833"
- style="opacity:1.0000000;fill:#6b6b75;fill-opacity:1.0000000;stroke:none;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
- <image
- id="image1821"
- height="428"
- width="572"
- sodipodi:absref="/home/alver/jabref/src/images/splashBackground.png"
- xlink:href="splashBackground.png"
- x="79"
- y="172.36218"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- inkscape:export-xdpi="75"
- inkscape:export-ydpi="75" />
- <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="opacity:1.0000000;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
- transform="matrix(1.875133,0.000000,0.000000,2.542210,-129.6969,-372.8897)"
- id="flowRoot2189"
- xml:space="preserve">
- <flowRegion
- id="flowRegion2191">
- <rect
- style="fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-opacity:1.0000000;stroke-width:0.48137557;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-linejoin:bevel"
- y="199.10532"
- x="128.49385"
- height="127.49445"
- width="283.51782"
- id="rect2193" />
- </flowRegion>
- <flowPara
- style="font-size:90.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;font-family:AR PL KaitiM GB"
- id="flowPara2201">JabRef</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#5cc757;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- transform="matrix(2.869197,-1.415830e-2,2.234317e-2,3.356271,-832.1435,-652.0185)"
- id="flowRoot2203"
- xml:space="preserve">
- <flowRegion
- style="stroke:url(#linearGradient5367);stroke-width:0.64448702;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091"
- id="flowRegion2205">
- <rect
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- y="286.45224"
- x="443.95346"
- height="119.83134"
- width="173.972"
- id="rect2207" />
- </flowRegion>
- <flowPara
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- id="flowPara2211">2.1</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="matrix(0.972246,0.000000,0.000000,1.325301,6.054966,-126.1181)"
- style="font-size:11.9999996;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;text-align:center;line-height:100%"
- id="flowRoot3076"
- xml:space="preserve"><flowRegion
- id="flowRegion3078">
- <rect
- style="fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;font-weight:bold;font-style:oblique;font-stretch:normal;font-variant:normal;font-size:11.9999996;text-anchor:middle;text-align:center;writing-mode:lr;line-height:100%"
- y="514.56494"
- x="115.50008"
- height="78.684433"
- width="506.03476"
- id="rect3080" />
- </flowRegion><flowPara
- id="flowPara1339">This program is distributed under the terms of the General Public License.</flowPara><flowPara
- id="flowPara1341">Copyright (2003-2006) Morten O. Alver, Nizar Batada and all contributors.</flowPara></flowRoot> <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="scale(0.853277,1.171952)"
- sodipodi:linespacing="100%"
- id="text1393"
- y="315.20035"
- x="163.38908"
- style="font-size:183.29680;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#413b62;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="315.20035"
- x="163.38908"
- id="tspan1395"
- sodipodi:role="line">JabRef</tspan></text>
- <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- transform="scale(0.853347,1.171856)"
- sodipodi:linespacing="100%"
- id="text2179"
- y="397.84811"
- x="149.99753"
- style="font-size:44.00000436;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#805b41;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr;text-align:start;line-height:100%"
- xml:space="preserve"><tspan
- y="397.84811"
- x="149.99753"
- id="tspan2181"
- sodipodi:role="line">reference manager</tspan></text>
- <text
- xml:space="preserve"
- style="font-size:68.76833344px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.66853937;fill:#cf5953;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Nimbus Sans L"
- x="288.67255"
- y="712.21191"
- id="text1343"
- sodipodi:linespacing="125%"
- transform="matrix(0.950669,-0.326025,0.330198,0.938651,0.000000,0.000000)"
- inkscape:export-filename="/home/alver/jabref-2.1b/src/images/splash-2.1beta.png"
- inkscape:export-xdpi="75"
- inkscape:export-ydpi="75"><tspan
- sodipodi:role="line"
- id="tspan1345"
- x="288.67255"
- y="712.21191">beta</tspan></text>
- </g>
-</svg>
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://web.resource.org/cc/"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash6.png"
- sodipodi:docname="splash.svg"
- sodipodi:docbase="/home/alver/jabref_beta/jabref/src/images"
- inkscape:version="0.42+0.43pre1"
- sodipodi:version="0.32"
- id="svg2138"
- height="1052.3622047"
- width="744.09448819">
- <defs
- id="defs2140">
- <pattern
- patternTransform="translate(316.0000,1046.362)"
- id="pattern9054"
- xlink:href="#pattern9048"
- inkscape:collect="always" />
- <linearGradient
- id="linearGradient5361"
- inkscape:collect="always">
- <stop
- id="stop5363"
- offset="0"
- style="stop-color:#000000;stop-opacity:1;" />
- <stop
- id="stop5365"
- offset="1"
- style="stop-color:#000000;stop-opacity:0;" />
- </linearGradient>
- <marker
- style="overflow:visible;"
- id="Arrow2Send"
- refX="0.0"
- refY="0.0"
- orient="auto"
- inkscape:stockid="Arrow2Send">
- <path
- transform="scale(0.3) rotate(180) translate(-5,0)"
- d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z "
- style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;"
- id="path3046"
- sodipodi:nodetypes="cccc" />
- </marker>
- <linearGradient
- gradientUnits="userSpaceOnUse"
- y2="300.91277"
- x2="491.20592"
- y1="300.91277"
- x1="445.01770"
- id="linearGradient5367"
- xlink:href="#linearGradient5361"
- inkscape:collect="always" />
- <pattern
- id="pattern9048"
- patternTransform="translate(231.0000,284.3622)"
- height="428.00000"
- width="572.00000"
- patternUnits="userSpaceOnUse">
- <image
- transform="translate(-231.0000,-284.3622)"
- style="opacity:1.0000000;stroke:#000000;stroke-width:5.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-opacity:1.0000000"
- inkscape:export-ydpi="90.000000"
- inkscape:export-xdpi="90.000000"
- inkscape:export-filename="/home/alver/Desktop/bilder/jabref/splash4.png"
- y="284.36218"
- x="231.00000"
- xlink:href="behandlet.png"
- sodipodi:absref="/home/alver/Desktop/bilder/jabref/behandlet.png"
- width="572.00000"
- height="428.00000"
- id="image9050" />
- </pattern>
- </defs>
- <sodipodi:namedview
- inkscape:window-y="80"
- inkscape:window-x="8"
- inkscape:window-height="856"
- inkscape:window-width="750"
- inkscape:current-layer="layer1"
- inkscape:document-units="px"
- inkscape:cy="698.1925"
- inkscape:cx="364.52617"
- inkscape:zoom="1"
- inkscape:pageshadow="2"
- inkscape:pageopacity="0.0"
- borderopacity="1.0"
- bordercolor="#666666"
- pagecolor="#ffffff"
- id="base" />
- <metadata
- id="metadata2143">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- </cc:Work>
- </rdf:RDF>
- </metadata>
- <g
- id="layer1"
- inkscape:groupmode="layer"
- inkscape:label="Layer 1">
- <rect
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- y="170.36218"
- x="77.500000"
- height="432.00000"
- width="576.00000"
- id="rect6833"
- style="opacity:1.0000000;fill:#6b6b75;fill-opacity:1.0000000;stroke:none;stroke-width:5.0000000;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000" />
- <image
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- y="172.36218"
- x="79.000000"
- id="image1390"
- height="428.00000"
- width="572.00000"
- sodipodi:absref="/home/alver/oldhome/bilder/bilder/jabref/behandlet.png"
- xlink:href="/home/alver/oldhome/bilder/bilder/jabref/behandlet.png" />
- <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="opacity:1.0000000;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000"
- transform="matrix(1.875133,0.000000,0.000000,2.542210,-129.6969,-372.8897)"
- id="flowRoot2189"
- xml:space="preserve">
- <flowRegion
- id="flowRegion2191">
- <rect
- style="fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-opacity:1.0000000;stroke-width:0.48137557;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-linejoin:bevel"
- y="199.10532"
- x="128.49385"
- height="127.49445"
- width="283.51782"
- id="rect2193" />
- </flowRegion>
- <flowPara
- style="font-size:90.000000px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr-tb;text-anchor:start;fill:#635578;fill-opacity:1.0000000;stroke:#b5b5c7;stroke-width:0.48137558;stroke-linejoin:bevel;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;font-family:AR PL KaitiM GB"
- id="flowPara2201">JabRef</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:1;stroke:#5cc757;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- transform="matrix(2.869197,-1.415830e-2,2.234317e-2,3.356271,-832.1435,-652.0185)"
- id="flowRoot2203"
- xml:space="preserve">
- <flowRegion
- style="stroke:url(#linearGradient5367);stroke-width:0.64448702;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091"
- id="flowRegion2205">
- <rect
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- y="286.45224"
- x="443.95346"
- height="119.83134"
- width="173.972"
- id="rect2207" />
- </flowRegion>
- <flowPara
- style="font-size:34.96500015px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:104.16220427%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:#322b5b;stroke-width:0.64448702;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:0.64448701 0.64448701 ;stroke-dashoffset:0.45114091;stroke-opacity:1;font-family:FreeSans"
- id="flowPara2211">2.0</flowPara>
- </flowRoot> <flowRoot
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="matrix(0.972246,0.000000,0.000000,1.325301,6.054966,-126.1181)"
- style="font-size:11.9999996;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;text-align:center;line-height:100%"
- id="flowRoot3076"
- xml:space="preserve"><flowRegion
- id="flowRegion3078">
- <rect
- style="fill:#797580;fill-opacity:1.0000000;font-family:Bitstream Vera Sans;font-weight:bold;font-style:oblique;font-stretch:normal;font-variant:normal;font-size:11.9999996;text-anchor:middle;text-align:center;writing-mode:lr;line-height:100%"
- y="514.56494"
- x="115.50008"
- height="78.684433"
- width="506.03476"
- id="rect3080" />
- </flowRegion><flowPara
- id="flowPara1339">This program is distributed under the terms of the General Public License.</flowPara><flowPara
- id="flowPara1341">Copyright (2003-2006) Morten O. Alver, Nizar Batada and all contributors.</flowPara></flowRoot> <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="scale(0.853277,1.171952)"
- sodipodi:linespacing="100%"
- id="text1393"
- y="315.20035"
- x="163.38908"
- style="font-size:183.29680;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#413b62;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Nimbus Roman No9 L;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="315.20035"
- x="163.38908"
- id="tspan1395"
- sodipodi:role="line">JabRef</tspan></text>
- <text
- inkscape:export-ydpi="75.000000"
- inkscape:export-xdpi="75.000000"
- inkscape:export-filename="/home/alver/jabref_beta/jabref/jabref-2.0-splash.png"
- transform="scale(0.853347,1.171856)"
- sodipodi:linespacing="100%"
- id="text2179"
- y="397.84811"
- x="149.99753"
- style="font-size:45.702374;font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#805b41;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Times New Roman;text-anchor:start;writing-mode:lr-tb"
- xml:space="preserve"><tspan
- y="397.84811"
- x="149.99753"
- id="tspan2181"
- sodipodi:role="line">reference manager</tspan></text>
- </g>
-</svg>
import java.util.WeakHashMap;
/**
- * This is an immutable class representing information of either
- * <CODE>author</CODE> or <CODE>editor</CODE> field in bibtex record.
+ * This is an immutable class representing information of either <CODE>author</CODE>
+ * or <CODE>editor</CODE> field in bibtex record.
* <p>
* Constructor performs parsing of raw field text and stores preformatted data.
* Various accessor methods return author/editor field in different formats.
* <p>
- * Parsing algorithm is designed to satisfy two requirements:
- * (a) when author's name is typed correctly, the result should
- * coincide with the one of BiBTeX;
- * (b) for erroneous names, output should be reasonable (but may differ
- * from BiBTeX output).
- * The following rules are used:
+ * Parsing algorithm is designed to satisfy two requirements: (a) when author's
+ * name is typed correctly, the result should coincide with the one of BiBTeX;
+ * (b) for erroneous names, output should be reasonable (but may differ from
+ * BiBTeX output). The following rules are used:
* <ol>
* <li> 'author field' is a sequence of tokens;
- * <ul>
- * <li> tokens are separated by sequences of whitespaces
- * (<CODE>Character.isWhitespace(c)==true</CODE>), commas (,),
- * dashes (-), and tildas (~);
- * <li> every comma separates tokens, while sequences of other separators
- * are equivalent to a single separator; for example:
- * "a - b" consists of 2 tokens ("a" and "b"), while
- * "a,-,b" consists of 3 tokens ("a", "", and "b")
- * <li> anything enclosed in braces belonges to a single token; for example:
- * "abc x{a,b,-~ c}x" consists of 2 tokens, while
- * "abc xa,b,-~ cx" consists of 4 tokens ("abc", "xa","b", and "cx");
- * <li> a token followed immediately by a dash is "dash-terminated" token,
- * and all other tokens are "space-terminated" tokens; for example:
- * in "a-b- c - d" tokens "a" and "b" are dash-terminated and
- * "c" and "d" are space-terminated;
- * <li> for the purposes of splitting of 'author name' into parts and
- * construction of abbreviation of first name,
- * one needs definitions of first latter of a token, case of a token,
- * and abbreviation of a token:
- * <ul>
- * <li> 'first letter' of a token is the first letter character
- * (<CODE>Character.isLetter(c)==true</CODE>) that does not
- * belong to a sequence of letters that immediately follows
- * "\" character, with one exception:
- * if "\" is followed by "aa", "AA", "ae", "AE", "l", "L", "o", "O",
- * "oe", "OE", "i", or "j" followed by non-letter, the 'first letter'
- * of a token is a letter that follows "\"; for example:
- * in "a{x}b" 'first letter' is "a",
- * in "{\"{U}}bel" 'first letter' is "U",
- * in "{\noopsort{\"o}}xyz" 'first letter' is "o",
- * in "{\AE}x" 'first letter' is "A",
- * in "\aex\ijk\Oe\j" 'first letter' is "j";
- * if there is no letter satisfying the above rule, 'first letter'
- * is undefined;
- * <li> token is "lower-case" token, if its first letter id defined and
- * is lower-case (<CODE>Character.isLowerCase(c)==true</CODE>),
- * and token is "upper-case" token otherwise;
- * <li> 'abbreviation' of a token is the shortest prefix of the token
- * that (a) contains 'first letter' and (b) is braces-balanced;
- * if 'first letter' is undefined, 'abbreviation' is the token
- * itself; in the above examples, 'abbreviation's are
- * "a", "{\"{U}}", "{\noopsort{\"o}}", "{\AE}", "\aex\ijk\Oe\j";
- * </ul>
- * <li> the behavior based on the above definitions will be erroneous only
- * in one case: if the first-name-token is "{\noopsort{A}}john",
- * we abbreviate it as "{\noopsort{A}}.", while BiBTeX produces "j.";
- * fixing this problem, however, requires processing of the preabmle;
- * </ul>
- * <li> 'author name's in 'author field' are subsequences of tokens separated
- * by token "and" ("and" is case-insensitive); if 'author name' is an
- * empty sequence of tokens, it is ignored; for examle, both
- * "John Smith and Peter Black" and "and and John Smith and and Peter Black"
- * consists of 2 'author name's "Johm Smith" and "Peter Black"
- * (in erroneous situations, this is a bit different from BiBTeX behavior);
+ * <ul>
+ * <li> tokens are separated by sequences of whitespaces (<CODE>Character.isWhitespace(c)==true</CODE>),
+ * commas (,), dashes (-), and tildas (~);
+ * <li> every comma separates tokens, while sequences of other separators are
+ * equivalent to a single separator; for example: "a - b" consists of 2 tokens
+ * ("a" and "b"), while "a,-,b" consists of 3 tokens ("a", "", and "b")
+ * <li> anything enclosed in braces belonges to a single token; for example:
+ * "abc x{a,b,-~ c}x" consists of 2 tokens, while "abc xa,b,-~ cx" consists of 4
+ * tokens ("abc", "xa","b", and "cx");
+ * <li> a token followed immediately by a dash is "dash-terminated" token, and
+ * all other tokens are "space-terminated" tokens; for example: in "a-b- c - d"
+ * tokens "a" and "b" are dash-terminated and "c" and "d" are space-terminated;
+ * <li> for the purposes of splitting of 'author name' into parts and
+ * construction of abbreviation of first name, one needs definitions of first
+ * latter of a token, case of a token, and abbreviation of a token:
+ * <ul>
+ * <li> 'first letter' of a token is the first letter character (<CODE>Character.isLetter(c)==true</CODE>)
+ * that does not belong to a sequence of letters that immediately follows "\"
+ * character, with one exception: if "\" is followed by "aa", "AA", "ae", "AE",
+ * "l", "L", "o", "O", "oe", "OE", "i", or "j" followed by non-letter, the
+ * 'first letter' of a token is a letter that follows "\"; for example: in
+ * "a{x}b" 'first letter' is "a", in "{\"{U}}bel" 'first letter' is "U", in
+ * "{\noopsort{\"o}}xyz" 'first letter' is "o", in "{\AE}x" 'first letter' is
+ * "A", in "\aex\ijk\Oe\j" 'first letter' is "j"; if there is no letter
+ * satisfying the above rule, 'first letter' is undefined;
+ * <li> token is "lower-case" token, if its first letter id defined and is
+ * lower-case (<CODE>Character.isLowerCase(c)==true</CODE>), and token is
+ * "upper-case" token otherwise;
+ * <li> 'abbreviation' of a token is the shortest prefix of the token that (a)
+ * contains 'first letter' and (b) is braces-balanced; if 'first letter' is
+ * undefined, 'abbreviation' is the token itself; in the above examples,
+ * 'abbreviation's are "a", "{\"{U}}", "{\noopsort{\"o}}", "{\AE}",
+ * "\aex\ijk\Oe\j";
+ * </ul>
+ * <li> the behavior based on the above definitions will be erroneous only in
+ * one case: if the first-name-token is "{\noopsort{A}}john", we abbreviate it
+ * as "{\noopsort{A}}.", while BiBTeX produces "j."; fixing this problem,
+ * however, requires processing of the preabmle;
+ * </ul>
+ * <li> 'author name's in 'author field' are subsequences of tokens separated by
+ * token "and" ("and" is case-insensitive); if 'author name' is an empty
+ * sequence of tokens, it is ignored; for examle, both "John Smith and Peter
+ * Black" and "and and John Smith and and Peter Black" consists of 2 'author
+ * name's "Johm Smith" and "Peter Black" (in erroneous situations, this is a bit
+ * different from BiBTeX behavior);
* <li> 'author name' consists of 'first-part', 'von-part', 'last-part', and
- * 'junior-part', each of which is a sequence of tokens;
- * how a sequence of tokens has to be splitted into these parts, depends
- * the number of commas:
- * <ul>
- * <li> no commas, all tokens are upper-case:
- * 'junior-part' and 'von-part' are empty, 'last-part' consist
- * of the last token, 'first-part' consists of all other tokens
- * ('first-part' is empty, if 'author name' consists of a single token);
- * for example, in "John James Smith", 'last-part'="Smith" and
- * 'first-part'="John James";
- * <li> no commas, there exists lower-case token:
- * 'junior-part' is empty, 'first-part' consists of all upper-case
- * tokens before the first lower-case token, 'von-part' consists of
- * lower-case tokens starting the first lower-case token and ending
- * the lower-case token that is followed by upper-case token,
- * 'last-part' consists of the rest of tokens;
- * note that both 'first-part' and 'latst-part' may be empty and
- * 'last-part' may contain lower-case tokens; for example:
- * in "von der", 'first-part'='last-part'="", 'von-part'="von der";
- * in "Charles Louis Xavier Joseph de la Vall{\'e}e la Poussin",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin";
- * <li> one comma:
- * 'junior-part' is empty, 'first-part' consists of all tokens after comma,
- * 'von-part' consists of the longest sequence of lower-case tokens
- * in the very beginning, 'last-part' consists of all tokens after
- * 'von-part' and before comma; note that any part can be empty;
- * for example: in "de la Vall{\'e}e la Poussin, Charles Louis Xavier Joseph",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin";
- * in "Joseph de la Vall{\'e}e la Poussin, Charles Louis Xavier",
- * 'first-part'="Charles Louis Xavier", 'von-part'="",
- * 'last-part'="Joseph de la Vall{\'e}e la Poussin";
- * <li> two or more commas (any comma after the second one is ignored;
- * it merely separates tokens):
- * 'junior-part' consists of all tokens between first and second commas,
- * 'first-part' consists of all tokens after the second comma,
- * tokens before the first comma are splitted into 'von-part' and
- * 'last-part' similarly to the case of one comma; for example:
- * in "de la Vall{\'e}e Poussin, Jr., Charles Louis Xavier Joseph",
- * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
- * 'last-part'="Vall{\'e}e la Poussin", and 'junior-part'="Jr.";
- * </ul>
- * <li> when 'first-part', 'last-part', 'von-part', or 'junior-part' is reconstructed
- * from tokens, tokens in a part are separated either by space or by dash,
- * depending on whether the token before the separator was space-terminated
- * or dash-terminated; for the last token in a part it does not matter
- * whether it was dash- or space-terminated;
- * <li> when 'first-part' is abbreviated, each token is replaced by its abbreviation
- * followed by a period; separators are the same as in the case of non-abbreviated
- * name; for example: in "Heinrich-{\"{U}}bel Kurt von Minich",
- * 'first-part'="Heinrich-{\"{U}}bel Kurt", and its abbreviation is
- * "H.-{\"{U}}. K."
+ * 'junior-part', each of which is a sequence of tokens; how a sequence of
+ * tokens has to be splitted into these parts, depends the number of commas:
+ * <ul>
+ * <li> no commas, all tokens are upper-case: 'junior-part' and 'von-part' are
+ * empty, 'last-part' consist of the last token, 'first-part' consists of all
+ * other tokens ('first-part' is empty, if 'author name' consists of a single
+ * token); for example, in "John James Smith", 'last-part'="Smith" and
+ * 'first-part'="John James";
+ * <li> no commas, there exists lower-case token: 'junior-part' is empty,
+ * 'first-part' consists of all upper-case tokens before the first lower-case
+ * token, 'von-part' consists of lower-case tokens starting the first lower-case
+ * token and ending the lower-case token that is followed by upper-case token,
+ * 'last-part' consists of the rest of tokens; note that both 'first-part' and
+ * 'latst-part' may be empty and 'last-part' may contain lower-case tokens; for
+ * example: in "von der", 'first-part'='last-part'="", 'von-part'="von der"; in
+ * "Charles Louis Xavier Joseph de la Vall{\'e}e la Poussin",
+ * 'first-part'="Charles Louis Xavier Joseph", 'von-part'="de la",
+ * 'last-part'="Vall{\'e}e la Poussin";
+ * <li> one comma: 'junior-part' is empty, 'first-part' consists of all tokens
+ * after comma, 'von-part' consists of the longest sequence of lower-case tokens
+ * in the very beginning, 'last-part' consists of all tokens after 'von-part'
+ * and before comma; note that any part can be empty; for example: in "de la
+ * Vall{\'e}e la Poussin, Charles Louis Xavier Joseph", 'first-part'="Charles
+ * Louis Xavier Joseph", 'von-part'="de la", 'last-part'="Vall{\'e}e la
+ * Poussin"; in "Joseph de la Vall{\'e}e la Poussin, Charles Louis Xavier",
+ * 'first-part'="Charles Louis Xavier", 'von-part'="", 'last-part'="Joseph de la
+ * Vall{\'e}e la Poussin";
+ * <li> two or more commas (any comma after the second one is ignored; it merely
+ * separates tokens): 'junior-part' consists of all tokens between first and
+ * second commas, 'first-part' consists of all tokens after the second comma,
+ * tokens before the first comma are splitted into 'von-part' and 'last-part'
+ * similarly to the case of one comma; for example: in "de la Vall{\'e}e
+ * Poussin, Jr., Charles Louis Xavier Joseph", 'first-part'="Charles Louis
+ * Xavier Joseph", 'von-part'="de la", 'last-part'="Vall{\'e}e la Poussin", and
+ * 'junior-part'="Jr.";
+ * </ul>
+ * <li> when 'first-part', 'last-part', 'von-part', or 'junior-part' is
+ * reconstructed from tokens, tokens in a part are separated either by space or
+ * by dash, depending on whether the token before the separator was
+ * space-terminated or dash-terminated; for the last token in a part it does not
+ * matter whether it was dash- or space-terminated;
+ * <li> when 'first-part' is abbreviated, each token is replaced by its
+ * abbreviation followed by a period; separators are the same as in the case of
+ * non-abbreviated name; for example: in "Heinrich-{\"{U}}bel Kurt von Minich",
+ * 'first-part'="Heinrich-{\"{U}}bel Kurt", and its abbreviation is "H.-{\"{U}}.
+ * K."
* </ol>
+ *
+ * @see tests.net.sf.jabref.AuthorListTest Testcases for this class.
*/
public class AuthorList {
- private Vector authors; // of Author
-
- // Variables for storing computed strings, so they only need be created once:
- private String authorsNatbib=null, authorsLastOnly=null, authorsLastFirst=null, authorLastFirstAnds=null,
- authorsFirstFirst=null, authorsFirstFirstAnds=null, authorsAlph=null;
-
-
- // The following variables are used only during parsing
-
- private String orig; // the raw bibtex author/editor field
- // the following variables are updated by getToken procedure
- private int token_start; // index in orig
- private int token_end; // to point 'abc' in ' abc xyz', start=2 and end=5
- // the following variables are valid only if getToken returns TOKEN_WORD
- private int token_abbr; // end of token abbreviation (always: token_start < token_abbr <= token_end)
- private char token_term; // either space or dash
- private boolean token_case; // true if upper-case token, false if lower-case token
-
- // Tokens of one author name.
- // Each token occupies TGL consecutive entries in this vector (as described below)
- private Vector tokens;
- private static final int TOKEN_GROUP_LENGTH = 4; // number of entries for a token
- // the following are offsets of an entry in a group of entries for one token
- private static final int OFFSET_TOKEN = 0; // String -- token itself;
- private static final int OFFSET_TOKEN_ABBR = 1; // String -- token abbreviation;
- private static final int OFFSET_TOKEN_TERM = 2; // Character -- token terminator (either " " or "-")
- //private static final int OFFSET_TOKEN_CASE = 3; // Boolean -- true=uppercase, false=lowercase
- // the following are indices in 'tokens' vector created during parsing of author name
- // and later used to properly split author name into parts
- int von_start, // first lower-case token (-1 if all tokens upper-case)
- last_start, // first upper-case token after first lower-case token (-1 if does not exist)
- comma_first, // token after first comma (-1 if no commas)
- comma_second; // token after second comma (-1 if no commas or only one comma)
-
- // Token types (returned by getToken procedure)
- private static final int TOKEN_EOF = 0;
- private static final int TOKEN_AND = 1;
- private static final int TOKEN_COMMA = 2;
- private static final int TOKEN_WORD = 3;
-
- // Constant Hashtable containing names of TeX special characters
- private static final java.util.Hashtable tex_names = new java.util.Hashtable();
- // and static constructor to initialize it
- static {
- tex_names.put("aa","aa"); // only keys are important in this table
- tex_names.put("ae","ae");
- tex_names.put("l","l");
- tex_names.put("o","o");
- tex_names.put("oe","oe");
- tex_names.put("i","i");
- tex_names.put("AA","AA");
- tex_names.put("AE","AE");
- tex_names.put("L","L");
- tex_names.put("O","O");
- tex_names.put("OE","OE");
- tex_names.put("j","j");
- }
-
- static WeakHashMap authorCache = new WeakHashMap();
-
- /**
- * Parses the parameter strings and stores preformatted author information.
- * @param bibtex_authors contents of either <CODE>author</CODE> or
- * <CODE>editor</CODE> bibtex field.
- */
- public AuthorList (String bibtex_authors) {
- authors = new Vector(5); // 5 seems to be reasonable initial size
- orig = bibtex_authors; // initialization
- token_start = 0; token_end = 0; // of parser
- while (token_start < orig.length()) {
- Author author = getAuthor();
- if (author != null) authors.add(author);
- }
- // clean-up
- orig = null; tokens = null;
- }
-
- public static String fixAuthor_Natbib(final String inOrig) {
- AuthorList authors = new AuthorList(inOrig);
- return authors.getAuthorsNatbib();
- }
-
- public static AuthorList getAuthorList(String inOrig) {
- Object o = authorCache.get(inOrig);
- if (o == null) {
- AuthorList authors = new AuthorList(inOrig);
- authorCache.put(inOrig, authors);
- return authors;
- } else
- return (AuthorList)o;
- }
-
- public static String fixAuthor_firstNameFirstCommas(final String inOrig, final boolean abbr) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsFirstFirst(abbr);
- }
-
- public static String fixAuthor_firstNameFirst(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsFirstFirstAnds();
- }
-
- public static String fixAuthor_lastNameFirstCommas(final String inOrig, final boolean abbr) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastFirst(abbr);
- }
-
- public static String fixAuthor_lastNameFirst(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastFirstAnds();
- }
-
- public static String fixAuthor_lastNameOnlyCommas(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsLastOnly();
- }
-
- public static String fixAuthorForAlphabetization(final String inOrig) {
- AuthorList authors = getAuthorList(inOrig);
- return authors.getAuthorsForAlphabetization();
-
- }
-
-
- /**
- * Parses one author name and returns preformatted information.
- * @return Preformatted author name; <CODE>null</CODE> if author name is empty.
- */
- private Author getAuthor() {
-
- tokens = new Vector(); // initialization
- von_start = -1; last_start = -1; comma_first = -1; comma_second = -1;
-
- // First step: collect tokens in 'tokens' Vector and calculate indices
- token_loop:
- while (true) {
- int token = getToken();
- cases: switch (token) {
- case TOKEN_EOF : case TOKEN_AND : break token_loop;
- case TOKEN_COMMA :
- if (comma_first < 0) comma_first = tokens.size();
- else if (comma_second < 0) comma_second = tokens.size();
- break cases;
- case TOKEN_WORD :
- tokens.add(orig.substring(token_start, token_end));
- tokens.add(orig.substring(token_start, token_abbr));
- tokens.add(new Character(token_term));
- tokens.add(Boolean.valueOf(token_case));
- if (comma_first >= 0) break cases;
- if (last_start >= 0) break cases;
- if (von_start < 0) {
- if (!token_case) {
- von_start = tokens.size()-TOKEN_GROUP_LENGTH; break cases;
- }
- } else if (last_start < 0 && token_case) {
- last_start = tokens.size()-TOKEN_GROUP_LENGTH; break cases;
- }
- }
- }// end token_loop
-
- // Second step: split name into parts (here: calculate indices
- // of parts in 'tokens' Vector)
- if (tokens.size()==0) return null; // no author information
-
- // the following negatives indicate absence of the corresponding part
- int first_part_start=-1, von_part_start=-1, last_part_start=-1, jr_part_start=-1;
- int first_part_end=0, von_part_end=0, last_part_end=0, jr_part_end=0;
- if (comma_first<0) { // no commas
- if (von_start<0) { // no 'von part'
- last_part_end = tokens.size();
- last_part_start = tokens.size() - TOKEN_GROUP_LENGTH;
- first_part_end = last_part_start;
- if (first_part_end>0) first_part_start = 0;
- } else { // 'von part' is present
- if (last_start>=0) {
- last_part_end = tokens.size();
- last_part_start = last_start;
- von_part_end = last_part_start;
- } else {
- von_part_end = tokens.size();
- }
- von_part_start = von_start;
- first_part_end = von_part_start;
- if (first_part_end>0) first_part_start = 0;
- }
- } else { // commas are present: it affects only 'first part' and 'junior part'
- first_part_end = tokens.size();
- if (comma_second<0) { // one comma
- if (comma_first < first_part_end) first_part_start = comma_first;
- } else { // two or more commas
- if (comma_second < first_part_end) first_part_start = comma_second;
- jr_part_end = comma_second;
- if (comma_first < jr_part_end) jr_part_start = comma_first;
- }
- if (von_start!=0) { // no 'von part'
- last_part_end = comma_first;
- if (last_part_end>0) last_part_start = 0;
- } else { // 'von part' is present
- if (last_start<0) {
- von_part_end = comma_first;
- } else {
- last_part_end = comma_first;
- last_part_start = last_start;
- von_part_end = last_part_start;
- }
- von_part_start = 0;
- }
- }
-
- // Third step: do actual splitting, construct Author object
- return new Author(
- (first_part_start<0 ? null : concatTokens(first_part_start,first_part_end,OFFSET_TOKEN,false)),
- (first_part_start<0 ? null : concatTokens(first_part_start,first_part_end,OFFSET_TOKEN_ABBR,true)),
- ( von_part_start<0 ? null : concatTokens( von_part_start, von_part_end,OFFSET_TOKEN,false)),
- ( last_part_start<0 ? null : concatTokens( last_part_start, last_part_end,OFFSET_TOKEN,false)),
- ( jr_part_start<0 ? null : concatTokens( jr_part_start, jr_part_end,OFFSET_TOKEN,false))
- );
- }
-
- /**
- * Concatenates list of tokens from 'tokens' Vector.
- * Tokens are separated by spaces or dashes, dependeing on stored in 'tokens'.
- * Callers always ensure that start < end; thus, there exists at least
- * one token to be concatenated.
- * @param start index of the first token to be concatenated in 'tokens' Vector
- * (always divisible by TOKEN_GROUP_LENGTH).
- * @param end index of the first token not to be concatenated in 'tokens' Vector
- * (always divisible by TOKEN_GROUP_LENGTH).
- * @param offset offset within token group (used to request concatenation of
- * either full tokens or abbreviation).
- * @param dot_after <CODE>true</CODE> -- add period after each token,
- * <CODE>false</CODE> -- do not add.
- * @return the result of concatenation.
- */
- private String concatTokens(int start, int end, int offset, boolean dot_after) {
- StringBuffer res = new StringBuffer();
- // Here we always have start < end
- res.append((String) tokens.get(start+offset));
- if (dot_after) res.append('.');
- start += TOKEN_GROUP_LENGTH;
- while (start < end) {
- res.append(tokens.get(start-TOKEN_GROUP_LENGTH+OFFSET_TOKEN_TERM));
- res.append((String) tokens.get(start+offset));
- if (dot_after) res.append('.');
- start += TOKEN_GROUP_LENGTH;
- }
- return res.toString();
- }
-
- /**
- * Parses the next token.
- * <p>
- * The string being parsed is stored in global variable <CODE>orig</CODE>,
- * and position which parsing has to start from is stored in global
- * variable <CODE>token_end</CODE>; thus, <CODE>token_end</CODE> has to be
- * set to 0 before the first invocation. Procedure updates <CODE>token_end</CODE>;
- * thus, subsequent invocations do not require any additional variable settings.
- * <p>
- * The type of the token is returned; if it is <CODE>TOKEN_WORD</CODE>, additional
- * information is given in global variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
- * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and <CODE>token_case</CODE>;
- * namely: <CODE>orig.substring(token_start,token_end)</CODE> is the thext of the token,
- * <CODE>orig.substring(token_start,token_abbr)</CODE> is the token abbreviation,
- * <CODE>token_term</CODE> contains token terminator (space or dash),
- * and <CODE>token_case</CODE> is <CODE>true</CODE>, if token is upper-case
- * and <CODE>false</CODE> if token is lower-case.
- * @return <CODE>TOKEN_EOF</CODE> -- no more tokens,
- * <CODE>TOKEN_COMMA</CODE> -- token is comma,
- * <CODE>TOKEN_AND</CODE> -- token is the word "and" (or "And", or "aND", etc.),
- * <CODE>TOKEN_WORD</CODE> -- token is a word; additional information is given
- * in global variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
- * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and <CODE>token_case</CODE>.
- */
- private int getToken() {
- token_start = token_end;
- while (token_start < orig.length()) {
- char c = orig.charAt(token_start);
- if ( !(c=='~' || c=='-' || Character.isWhitespace(c)) ) break;
- token_start++;
- }
- token_end = token_start;
- if (token_start >= orig.length()) return TOKEN_EOF;
- if (orig.charAt(token_start)==',') { token_end++; return TOKEN_COMMA; }
- token_abbr = -1;
- token_term = ' ';
- token_case = true;
- int braces_level = 0;
- int current_backslash = -1;
- boolean first_letter_is_found = false;
- while (token_end < orig.length()) {
- char c = orig.charAt(token_end);
- if (c=='{') { braces_level++; }
- if (braces_level > 0) if (c=='}') braces_level--;
- if (first_letter_is_found && token_abbr<0 && braces_level==0) token_abbr = token_end;
- if (!first_letter_is_found && current_backslash<0 && Character.isLetter(c)) {
- token_case = Character.isUpperCase(c); first_letter_is_found = true;
- }
- if (current_backslash>=0 && !Character.isLetter(c)) {
- if (!first_letter_is_found) {
- String tex_cmd_name = orig.substring(current_backslash+1, token_end);
- if (tex_names.get(tex_cmd_name)!=null) {
- token_case = Character.isUpperCase(tex_cmd_name.charAt(0));
- first_letter_is_found = true;
- }
- }
- current_backslash = -1;
- }
- if (c=='\\') current_backslash = token_end;
- if (braces_level==0)
- if (c==',' || c=='~' || /*c=='-' ||*/ Character.isWhitespace(c)) break;
- // Morten Alver 18 Apr 2006: Removed check for hyphen '-' above to prevent
- // problems with names like Bailey-Jones getting broken up and sorted wrong.
- token_end++;
- }
- if (token_abbr<0) token_abbr = token_end;
- if (token_end<orig.length() && orig.charAt(token_end)=='-') token_term='-';
- if (orig.substring(token_start,token_end).equalsIgnoreCase("and"))
- return TOKEN_AND; else return TOKEN_WORD;
- }
-
- /**
- * Returns the number of author names in this object.
- * @return the number of author names in this object.
- */
- public int size() { return authors.size(); }
- /**
- * Returns the <CODE>Author</CODE> object for ith author.
- * @param i index of the author (from 0 to <CODE>size()-1</CODE>).
- * @return the <CODE>Author</CODE> object.
- */
- public Author getAuthor(int i) { return (Author) authors.get(i); }
- /**
- * Returns the list of authors in "natbib" format.
- * <p>
- * "John Smith" ==> "Smith";
- * "John Smith and Black Brown, Peter" ==> "Smith and Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==> "von Neumann et al.".
- * @return formatted list of authors.
- */
- public String getAuthorsNatbib() {
- // Check if we've computed this before:
- if (authorsNatbib != null)
- return authorsNatbib;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastOnly());
- if (size()==2) {
- res.append(" and ");
- res.append(getAuthor(1).getLastOnly());
- } else if (size()>2) {
- res.append(" et al.");
- }
- }
- authorsNatbib = res.toString();
- return authorsNatbib;
- }
- /**
- * Returns the list of authors separated by commas with last name only;
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "Smith";
- * "John Smith and Black Brown, Peter" ==> "Smith and Black Brown" ;
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, Smith and Black Brown".
- * @return formatted list of authors.
- */
- public String getAuthorsLastOnly() {
- // Check if we've computed this before:
- if (authorsLastOnly != null)
- return authorsLastOnly;
- StringBuffer res = new StringBuffer();
- if (size() > 0) {
- res.append(getAuthor(0).getLastOnly());
- int i = 1;
- while (i < size() - 1) {
- res.append(", ");
- res.append(getAuthor(i).getLastOnly());
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getLastOnly());
- }
- }
- authorsLastOnly = res.toString();
- return authorsLastOnly;
- }
- /**
- * Returns the list of authors separated by commas with first names after last name;
- * first names are abbreviated or not depending on parameter.
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "Smith, John" or "Smith, J.";
- * "John Smith and Black Brown, Peter" ==>
- * "Smith, John and Black Brown, Peter" or "Smith, J. and Black Brown, P.";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, John, Smith, John and Black Brown, Peter" or
- * "von Neumann, J., Smith, J. and Black Brown, P.".
- * @param abbr <CODE>true</CODE> -- abbreviate first names,
- * <CODE>false</CODE> -- do not abbreviate.
- * @return formatted list of authors.
- */
- public String getAuthorsLastFirst(boolean abbr) {
- // Check if we've computed this before:
- if (authorsLastFirst != null)
- return authorsLastFirst;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastFirst(abbr));
- int i = 1;
- while (i < size()-1) {
- res.append(", ");
- res.append(getAuthor(i).getLastFirst(abbr));
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getLastFirst(abbr));
- }
- }
- authorsLastFirst = res.toString();
- return authorsLastFirst;
- }
- /**
- * Returns the list of authors separated by "and"s with first names after last name;
- * first names are not abbreviated.
- * <p>
- * "John Smith" ==> "Smith, John";
- * "John Smith and Black Brown, Peter" ==> "Smith, John and Black Brown, Peter";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "von Neumann, John and Smith, John and Black Brown, Peter".
- * @return formatted list of authors.
- */
- public String getAuthorsLastFirstAnds() {
- // Check if we've computed this before:
- if (authorLastFirstAnds != null)
- return authorLastFirstAnds;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getLastFirst(false));
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getLastFirst(false));
- }
- }
-
- authorLastFirstAnds = res.toString();
- return authorLastFirstAnds;
- }
- /**
- * Returns the list of authors separated by commas with first names before last name;
- * first names are abbreviated or not depending on parameter.
- * If the list consists of three or more authors, "and" is inserted before
- * the last author's name.
- * <p>
- * "John Smith" ==> "John Smith" or "J. Smith";
- * "John Smith and Black Brown, Peter" ==>
- * "John Smith and Peter Black Brown" or "J. Smith and P. Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "John von Neumann, John Smith and Peter Black Brown" or
- * "J. von Neumann, J. Smith and P. Black Brown".
- * @param abbr <CODE>true</CODE> -- abbreviate first names,
- * <CODE>false</CODE> -- do not abbreviate.
- * @return formatted list of authors.
- */
- public String getAuthorsFirstFirst(boolean abbr) {
- // Check if we've computed this before:
- if (authorsFirstFirst != null)
- return authorsFirstFirst;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getFirstLast(abbr));
- int i = 1;
- while (i < size()-1) {
- res.append(", ");
- res.append(getAuthor(i).getFirstLast(abbr));
- i++;
- }
- if (size() > 2) res.append(",");
- if (size() > 1) {
- res.append(" and ");
- res.append(getAuthor(i).getFirstLast(abbr));
- }
- }
- authorsFirstFirst = res.toString();
- return authorsFirstFirst;
- }
- /**
- * Returns the list of authors separated by "and"s with first names before last name;
- * first names are not abbreviated.
- * <p>
- * "John Smith" ==> "John Smith";
- * "John Smith and Black Brown, Peter" ==> "John Smith and Peter Black Brown";
- * "John von Neumann and John Smith and Black Brown, Peter" ==>
- * "John von Neumann and John Smith and Peter Black Brown".
- * @return formatted list of authors.
- */
- public String getAuthorsFirstFirstAnds() {
- // Check if we've computed this before:
- if (authorsFirstFirstAnds != null)
- return authorsFirstFirstAnds;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getFirstLast(false));
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getFirstLast(false));
- }
- }
- authorsFirstFirstAnds = res.toString();
- return authorsFirstFirstAnds;
- }
-
- /**
- * Returns the list of authors in a form suitable for alphabetization. This means that
- * last names come first, never preceded by "von" particles, and that any braces are
- * removed. First names are abbreviated so the same name is treated similarly if abbreviated
- * in one case and not in another.
- * This form is not intended to be suitable for presentation, only for sorting.
- *
- * <p>
- * "John Smith" ==> "Smith, J.";
- * "John von Neumann
- * @return formatted list of authors
- */
- public String getAuthorsForAlphabetization() {
- if (authorsAlph != null)
- return authorsAlph;
-
- StringBuffer res = new StringBuffer();
- if (size()>0) {
- res.append(getAuthor(0).getNameForAlphabetization());
- for (int i=1; i<size(); i++) {
- res.append(" and ");
- res.append(getAuthor(i).getNameForAlphabetization());
- }
- }
- authorsAlph = res.toString();
- return authorsAlph;
- }
-
-
-
- /**
- * This is an immutable class that keeps information regarding single author.
- * It is just a container for the information, with very simple methods
- * to access it.
- * <p>
- * Current usage: only methods <code>getLastOnly</code>,
- * <code>getFirstLast</code>, and <code>getLastFirst</code> are used;
- * all other methods are provided for completeness.
- */
- private static class Author {
- private final String first_part;
- private final String first_abbr;
- private final String von_part;
- private final String last_part;
- private final String jr_part;
- /**
- * Creates the Author object.
- * If any part of the name is absent, <CODE>null</CODE> must be passes;
- * otherwise other methods may return erroneous results.
- * @param first the first name of the author (may consist of several tokens,
- * like "Charles Louis Xavier Joseph" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param firstabbr the abbreviated first name of the author (may consist
- * of several tokens, like "C. L. X. J." in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin").
- * It is a responsibility of the caller to create a reasonable
- * abbreviation of the first name.
- * @param von the von part of the author's name (may consist of
- * several tokens, like "de la" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param last the lats name of the author (may consist of several tokens,
- * like "Vall{\'e}e Poussin" in
- * "Charles Louis Xavier Joseph de la Vall{\'e}e Poussin")
- * @param jr the junior part of the author's name (may consist of
- * several tokens, like "Jr. III" in
- * "Smith, Jr. III, John")
- */
- public Author(String first, String firstabbr, String von, String last, String jr) {
- first_part = first;
- first_abbr = firstabbr;
- von_part = von;
- last_part = last;
- jr_part = jr;
- }
- /**
- * Retunrns the first name of the author stored in this object.
- * @return first name of the author (may consist of several tokens)
- */
- public String getFirst() { return first_part; }
- /**
- * Retunrns the abbreviated first name of the author stored in this object.
- * @return abbreviated first name of the author (may consist of several tokens)
- */
- public String getFirstAbbr() { return first_abbr; }
- /**
- * Retunrns the von part of the author's name stored in this object.
- * @return von part of the author's name (may consist of several tokens)
- */
- public String getVon() { return von_part; }
- /**
- * Retunrns the last name of the author stored in this object.
- * @return last name of the author (may consist of several tokens)
- */
- public String getLast() { return last_part; }
- /**
- * Retunrns the junior part of the author's name stored in this object.
- * @return junior part of the author's name (may consist of several tokens)
- */
- public String getJr() { return jr_part; }
- /**
- * Returns von part followed by last name.
- * If both fields were specified as <CODE>null</CODE>,
- * the empty string <CODE>""</CODE> is returned.
- * @return 'von Last'
- */
- public String getLastOnly() {
- if (von_part==null) {
- return (last_part==null ? "" : last_part);
- } else {
- return (last_part==null ? von_part : von_part + " " + last_part);
- }
- }
- /**
- * Returns the author's name in form 'von Last, Jr., First' with the first name
- * full or abbreviated depending on parameter.
- * @param abbr <CODE>true</CODE> - abbreviate first name,
- * <CODE>false</CODE> - do not abbreviate
- * @return 'von Last, Jr., First' (if <CODE>abbr==false</CODE>) or
- * 'von Last, Jr., F.' (if <CODE>abbr==true</CODE>)
- */
- public String getLastFirst(boolean abbr) {
- String res = getLastOnly();
- if (jr_part != null) res += ", " + jr_part;
- if (abbr) {
- if (first_abbr != null) res += ", " + first_abbr;
- } else {
- if (first_part != null) res += ", " + first_part;
- }
- return res;
- }
- /**
- * Returns the author's name in form 'First von Last, Jr.' with the first name
- * full or abbreviated depending on parameter.
- * @param abbr <CODE>true</CODE> - abbreviate first name,
- * <CODE>false</CODE> - do not abbreviate
- * @return 'First von Last, Jr.' (if <CODE>abbr==false</CODE>) or
- * 'F. von Last, Jr.' (if <CODE>abbr==true</CODE>)
- */
- public String getFirstLast(boolean abbr) {
- String res = getLastOnly();
- if (abbr) {
- res = (first_abbr==null ? "" : first_abbr + " ") + res;
- } else {
- res = (first_part==null ? "" : first_part + " ") + res;
- }
- if (jr_part != null) res += ", " + jr_part;
- return res;
- }
-
- public String getNameForAlphabetization() {
- StringBuffer res = new StringBuffer();
- if (last_part != null)
- res.append(last_part);
- if (jr_part != null) {
- res.append(", ");
- res.append(jr_part);
- }
- if (first_abbr != null) {
- res.append(", ");
- res.append(first_abbr);
- }
- while ((res.length() > 0) && (res.charAt(0) == '{'))
- res.deleteCharAt(0);
- return res.toString();
-
- }
- }//end Author
-}//end AuthorList
+ private Vector authors; // of Author
+
+ // Variables for storing computed strings, so they only need be created
+ // once:
+ private String authorsNatbib = null, authorsFirstFirstAnds = null,
+ authorsAlph = null;
+
+ private String[] authorsFirstFirst = new String[4], authorsLastOnly = new String[2],
+ authorLastFirstAnds = new String[2],
+ authorsLastFirst = new String[4];
+
+ // The following variables are used only during parsing
+
+ private String orig; // the raw bibtex author/editor field
+
+ // the following variables are updated by getToken procedure
+ private int token_start; // index in orig
+
+ private int token_end; // to point 'abc' in ' abc xyz', start=2 and end=5
+
+ // the following variables are valid only if getToken returns TOKEN_WORD
+ private int token_abbr; // end of token abbreviation (always: token_start <
+
+ // token_abbr <= token_end)
+
+ private char token_term; // either space or dash
+
+ private boolean token_case; // true if upper-case token, false if lower-case
+
+ // token
+
+ // Tokens of one author name.
+ // Each token occupies TGL consecutive entries in this vector (as described
+ // below)
+ private Vector tokens;
+
+ private static final int TOKEN_GROUP_LENGTH = 4; // number of entries for
+
+ // a token
+
+ // the following are offsets of an entry in a group of entries for one token
+ private static final int OFFSET_TOKEN = 0; // String -- token itself;
+
+ private static final int OFFSET_TOKEN_ABBR = 1; // String -- token
+
+ // abbreviation;
+
+ private static final int OFFSET_TOKEN_TERM = 2; // Character -- token
+
+ // terminator (either " " or
+ // "-")
+
+ // private static final int OFFSET_TOKEN_CASE = 3; // Boolean --
+ // true=uppercase, false=lowercase
+ // the following are indices in 'tokens' vector created during parsing of
+ // author name
+ // and later used to properly split author name into parts
+ int von_start, // first lower-case token (-1 if all tokens upper-case)
+ last_start, // first upper-case token after first lower-case token (-1
+ // if does not exist)
+ comma_first, // token after first comma (-1 if no commas)
+ comma_second; // token after second comma (-1 if no commas or only one
+
+ // comma)
+
+ // Token types (returned by getToken procedure)
+ private static final int TOKEN_EOF = 0;
+
+ private static final int TOKEN_AND = 1;
+
+ private static final int TOKEN_COMMA = 2;
+
+ private static final int TOKEN_WORD = 3;
+
+ // Constant Hashtable containing names of TeX special characters
+ private static final java.util.Hashtable tex_names = new java.util.Hashtable();
+ // and static constructor to initialize it
+ static {
+ tex_names.put("aa", "aa"); // only keys are important in this table
+ tex_names.put("ae", "ae");
+ tex_names.put("l", "l");
+ tex_names.put("o", "o");
+ tex_names.put("oe", "oe");
+ tex_names.put("i", "i");
+ tex_names.put("AA", "AA");
+ tex_names.put("AE", "AE");
+ tex_names.put("L", "L");
+ tex_names.put("O", "O");
+ tex_names.put("OE", "OE");
+ tex_names.put("j", "j");
+ }
+
+ static WeakHashMap authorCache = new WeakHashMap();
+
+ /**
+ * Parses the parameter strings and stores preformatted author information.
+ *
+ * Don't call this constructor directly but rather use the getAuthorList()
+ * method which caches its results.
+ *
+ * @param bibtex_authors
+ * contents of either <CODE>author</CODE> or <CODE>editor</CODE>
+ * bibtex field.
+ */
+ protected AuthorList(String bibtex_authors) {
+ authors = new Vector(5); // 5 seems to be reasonable initial size
+ orig = bibtex_authors; // initialization
+ token_start = 0;
+ token_end = 0; // of parser
+ while (token_start < orig.length()) {
+ Author author = getAuthor();
+ if (author != null)
+ authors.add(author);
+ }
+ // clean-up
+ orig = null;
+ tokens = null;
+ }
+
+ /**
+ * Retrieve an AuthorList for the given string of authors or editors.
+ *
+ * This function tries to cache AuthorLists by string passed in.
+ *
+ * @param authors
+ * The string of authors or editors in bibtex format to parse.
+ * @return An AuthorList object representing the given authors.
+ */
+ public static AuthorList getAuthorList(String authors) {
+ AuthorList authorList = (AuthorList) authorCache.get(authors);
+ if (authorList == null) {
+ authorList = new AuthorList(authors);
+ authorCache.put(authors, authorList);
+ }
+ return authorList;
+ }
+
+ /**
+ * This is a convenience method for getAuthorsFirstFirst()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsFirstFirst
+ */
+ public static String fixAuthor_firstNameFirstCommas(String authors, boolean abbr,
+ boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsFirstFirst(abbr, oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsFirstFirstAnds()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsFirstFirstAnds
+ */
+ public static String fixAuthor_firstNameFirst(String authors) {
+ return getAuthorList(authors).getAuthorsFirstFirstAnds();
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirst()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirst
+ */
+ public static String fixAuthor_lastNameFirstCommas(String authors, boolean abbr,
+ boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsLastFirst(abbr, oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirstAnds(true)
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirstAnds
+ */
+ public static String fixAuthor_lastNameFirst(String authors) {
+ return getAuthorList(authors).getAuthorsLastFirstAnds(false);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastFirstAnds()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastFirstAnds
+ */
+ public static String fixAuthor_lastNameFirst(String authors, boolean abbreviate) {
+ return getAuthorList(authors).getAuthorsLastFirstAnds(abbreviate);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsLastOnly()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsLastOnly
+ */
+ public static String fixAuthor_lastNameOnlyCommas(String authors, boolean oxfordComma) {
+ return getAuthorList(authors).getAuthorsLastOnly(oxfordComma);
+ }
+
+ /**
+ * This is a convenience method for getAuthorsForAlphabetization()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsForAlphabetization
+ */
+ public static String fixAuthorForAlphabetization(String authors) {
+ return getAuthorList(authors).getAuthorsForAlphabetization();
+ }
+
+ /**
+ * This is a convenience method for getAuthorsNatbib()
+ *
+ * @see net.sf.jabref.AuthorList#getAuthorsNatbib
+ */
+ public static String fixAuthor_Natbib(String authors) {
+ return AuthorList.getAuthorList(authors).getAuthorsNatbib();
+ }
+
+ /**
+ * Parses one author name and returns preformatted information.
+ *
+ * @return Preformatted author name; <CODE>null</CODE> if author name is
+ * empty.
+ */
+ private Author getAuthor() {
+
+ tokens = new Vector(); // initialization
+ von_start = -1;
+ last_start = -1;
+ comma_first = -1;
+ comma_second = -1;
+
+ // First step: collect tokens in 'tokens' Vector and calculate indices
+ token_loop: while (true) {
+ int token = getToken();
+ cases: switch (token) {
+ case TOKEN_EOF:
+ case TOKEN_AND:
+ break token_loop;
+ case TOKEN_COMMA:
+ if (comma_first < 0)
+ comma_first = tokens.size();
+ else if (comma_second < 0)
+ comma_second = tokens.size();
+ break cases;
+ case TOKEN_WORD:
+ tokens.add(orig.substring(token_start, token_end));
+ tokens.add(orig.substring(token_start, token_abbr));
+ tokens.add(new Character(token_term));
+ tokens.add(Boolean.valueOf(token_case));
+ if (comma_first >= 0)
+ break cases;
+ if (last_start >= 0)
+ break cases;
+ if (von_start < 0) {
+ if (!token_case) {
+ von_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ break cases;
+ }
+ } else if (last_start < 0 && token_case) {
+ last_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ break cases;
+ }
+ }
+ }// end token_loop
+
+ // Second step: split name into parts (here: calculate indices
+ // of parts in 'tokens' Vector)
+ if (tokens.size() == 0)
+ return null; // no author information
+
+ // the following negatives indicate absence of the corresponding part
+ int first_part_start = -1, von_part_start = -1, last_part_start = -1, jr_part_start = -1;
+ int first_part_end = 0, von_part_end = 0, last_part_end = 0, jr_part_end = 0;
+ if (comma_first < 0) { // no commas
+ if (von_start < 0) { // no 'von part'
+ last_part_end = tokens.size();
+ last_part_start = tokens.size() - TOKEN_GROUP_LENGTH;
+ first_part_end = last_part_start;
+ if (first_part_end > 0)
+ first_part_start = 0;
+ } else { // 'von part' is present
+ if (last_start >= 0) {
+ last_part_end = tokens.size();
+ last_part_start = last_start;
+ von_part_end = last_part_start;
+ } else {
+ von_part_end = tokens.size();
+ }
+ von_part_start = von_start;
+ first_part_end = von_part_start;
+ if (first_part_end > 0)
+ first_part_start = 0;
+ }
+ } else { // commas are present: it affects only 'first part' and
+ // 'junior part'
+ first_part_end = tokens.size();
+ if (comma_second < 0) { // one comma
+ if (comma_first < first_part_end)
+ first_part_start = comma_first;
+ } else { // two or more commas
+ if (comma_second < first_part_end)
+ first_part_start = comma_second;
+ jr_part_end = comma_second;
+ if (comma_first < jr_part_end)
+ jr_part_start = comma_first;
+ }
+ if (von_start != 0) { // no 'von part'
+ last_part_end = comma_first;
+ if (last_part_end > 0)
+ last_part_start = 0;
+ } else { // 'von part' is present
+ if (last_start < 0) {
+ von_part_end = comma_first;
+ } else {
+ last_part_end = comma_first;
+ last_part_start = last_start;
+ von_part_end = last_part_start;
+ }
+ von_part_start = 0;
+ }
+ }
+
+ // Third step: do actual splitting, construct Author object
+ return new Author((first_part_start < 0 ? null : concatTokens(first_part_start,
+ first_part_end, OFFSET_TOKEN, false)), (first_part_start < 0 ? null : concatTokens(
+ first_part_start, first_part_end, OFFSET_TOKEN_ABBR, true)), (von_part_start < 0 ? null
+ : concatTokens(von_part_start, von_part_end, OFFSET_TOKEN, false)),
+ (last_part_start < 0 ? null : concatTokens(last_part_start, last_part_end,
+ OFFSET_TOKEN, false)), (jr_part_start < 0 ? null : concatTokens(jr_part_start,
+ jr_part_end, OFFSET_TOKEN, false)));
+ }
+
+ /**
+ * Concatenates list of tokens from 'tokens' Vector. Tokens are separated by
+ * spaces or dashes, dependeing on stored in 'tokens'. Callers always ensure
+ * that start < end; thus, there exists at least one token to be
+ * concatenated.
+ *
+ * @param start
+ * index of the first token to be concatenated in 'tokens' Vector
+ * (always divisible by TOKEN_GROUP_LENGTH).
+ * @param end
+ * index of the first token not to be concatenated in 'tokens'
+ * Vector (always divisible by TOKEN_GROUP_LENGTH).
+ * @param offset
+ * offset within token group (used to request concatenation of
+ * either full tokens or abbreviation).
+ * @param dot_after
+ * <CODE>true</CODE> -- add period after each token, <CODE>false</CODE> --
+ * do not add.
+ * @return the result of concatenation.
+ */
+ private String concatTokens(int start, int end, int offset, boolean dot_after) {
+ StringBuffer res = new StringBuffer();
+ // Here we always have start < end
+ res.append((String) tokens.get(start + offset));
+ if (dot_after)
+ res.append('.');
+ start += TOKEN_GROUP_LENGTH;
+ while (start < end) {
+ res.append(tokens.get(start - TOKEN_GROUP_LENGTH + OFFSET_TOKEN_TERM));
+ res.append((String) tokens.get(start + offset));
+ if (dot_after)
+ res.append('.');
+ start += TOKEN_GROUP_LENGTH;
+ }
+ return res.toString();
+ }
+
+ /**
+ * Parses the next token.
+ * <p>
+ * The string being parsed is stored in global variable <CODE>orig</CODE>,
+ * and position which parsing has to start from is stored in global variable
+ * <CODE>token_end</CODE>; thus, <CODE>token_end</CODE> has to be set
+ * to 0 before the first invocation. Procedure updates <CODE>token_end</CODE>;
+ * thus, subsequent invocations do not require any additional variable
+ * settings.
+ * <p>
+ * The type of the token is returned; if it is <CODE>TOKEN_WORD</CODE>,
+ * additional information is given in global variables <CODE>token_start</CODE>,
+ * <CODE>token_end</CODE>, <CODE>token_abbr</CODE>, <CODE>token_term</CODE>,
+ * and <CODE>token_case</CODE>; namely: <CODE>orig.substring(token_start,token_end)</CODE>
+ * is the thext of the token, <CODE>orig.substring(token_start,token_abbr)</CODE>
+ * is the token abbreviation, <CODE>token_term</CODE> contains token
+ * terminator (space or dash), and <CODE>token_case</CODE> is <CODE>true</CODE>,
+ * if token is upper-case and <CODE>false</CODE> if token is lower-case.
+ *
+ * @return <CODE>TOKEN_EOF</CODE> -- no more tokens, <CODE>TOKEN_COMMA</CODE> --
+ * token is comma, <CODE>TOKEN_AND</CODE> -- token is the word
+ * "and" (or "And", or "aND", etc.), <CODE>TOKEN_WORD</CODE> --
+ * token is a word; additional information is given in global
+ * variables <CODE>token_start</CODE>, <CODE>token_end</CODE>,
+ * <CODE>token_abbr</CODE>, <CODE>token_term</CODE>, and
+ * <CODE>token_case</CODE>.
+ */
+ private int getToken() {
+ token_start = token_end;
+ while (token_start < orig.length()) {
+ char c = orig.charAt(token_start);
+ if (!(c == '~' || c == '-' || Character.isWhitespace(c)))
+ break;
+ token_start++;
+ }
+ token_end = token_start;
+ if (token_start >= orig.length())
+ return TOKEN_EOF;
+ if (orig.charAt(token_start) == ',') {
+ token_end++;
+ return TOKEN_COMMA;
+ }
+ token_abbr = -1;
+ token_term = ' ';
+ token_case = true;
+ int braces_level = 0;
+ int current_backslash = -1;
+ boolean first_letter_is_found = false;
+ while (token_end < orig.length()) {
+ char c = orig.charAt(token_end);
+ if (c == '{') {
+ braces_level++;
+ }
+ if (braces_level > 0)
+ if (c == '}')
+ braces_level--;
+ if (first_letter_is_found && token_abbr < 0 && braces_level == 0)
+ token_abbr = token_end;
+ if (!first_letter_is_found && current_backslash < 0 && Character.isLetter(c)) {
+ token_case = Character.isUpperCase(c);
+ first_letter_is_found = true;
+ }
+ if (current_backslash >= 0 && !Character.isLetter(c)) {
+ if (!first_letter_is_found) {
+ String tex_cmd_name = orig.substring(current_backslash + 1, token_end);
+ if (tex_names.get(tex_cmd_name) != null) {
+ token_case = Character.isUpperCase(tex_cmd_name.charAt(0));
+ first_letter_is_found = true;
+ }
+ }
+ current_backslash = -1;
+ }
+ if (c == '\\')
+ current_backslash = token_end;
+ if (braces_level == 0)
+ if (c == ',' || c == '~' || /* c=='-' || */Character.isWhitespace(c))
+ break;
+ // Morten Alver 18 Apr 2006: Removed check for hyphen '-' above to
+ // prevent
+ // problems with names like Bailey-Jones getting broken up and
+ // sorted wrong.
+ token_end++;
+ }
+ if (token_abbr < 0)
+ token_abbr = token_end;
+ if (token_end < orig.length() && orig.charAt(token_end) == '-')
+ token_term = '-';
+ if (orig.substring(token_start, token_end).equalsIgnoreCase("and"))
+ return TOKEN_AND;
+ else
+ return TOKEN_WORD;
+ }
+
+ /**
+ * Returns the number of author names in this object.
+ *
+ * @return the number of author names in this object.
+ */
+ public int size() {
+ return authors.size();
+ }
+
+ /**
+ * Returns the <CODE>Author</CODE> object for the i-th author.
+ *
+ * @param i
+ * Index of the author (from 0 to <CODE>size()-1</CODE>).
+ * @return the <CODE>Author</CODE> object.
+ */
+ public Author getAuthor(int i) {
+ return (Author) authors.get(i);
+ }
+
+ /**
+ * Returns the list of authors in "natbib" format.
+ * <p>
+ * <ul>
+ * <li>"John Smith" -> "Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "Smith and Black Brown"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann et al." </li>
+ * </ul>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsNatbib() {
+ // Check if we've computed this before:
+ if (authorsNatbib != null)
+ return authorsNatbib;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastOnly());
+ if (size() == 2) {
+ res.append(" and ");
+ res.append(getAuthor(1).getLastOnly());
+ } else if (size() > 2) {
+ res.append(" et al.");
+ }
+ }
+ authorsNatbib = res.toString();
+ return authorsNatbib;
+ }
+
+ /**
+ * Returns the list of authors separated by commas with last name only; If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ *
+ * <ul>
+ * <li> "John Smith" ==> "Smith"</li>
+ * <li> "John Smith and Black Brown, Peter" ==> "Smith and Black Brown"</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, Smith and Black Brown".</li>
+ * </ul>
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastOnly(boolean oxfordComma) {
+
+ int abbrInt = (oxfordComma ? 0 : 1);
+
+ // Check if we've computed this before:
+ if (authorsLastOnly[abbrInt] != null)
+ return authorsLastOnly[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastOnly());
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getLastOnly());
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastOnly());
+ }
+ }
+ authorsLastOnly[abbrInt] = res.toString();
+ return authorsLastOnly[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by commas with first names after
+ * last name; first names are abbreviated or not depending on parameter. If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ *
+ * <ul>
+ * <li> "John Smith" ==> "Smith, John" or "Smith, J."</li>
+ * <li> "John Smith and Black Brown, Peter" ==> "Smith, John and Black
+ * Brown, Peter" or "Smith, J. and Black Brown, P."</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, John, Smith, John and Black Brown, Peter" or "von Neumann, J.,
+ * Smith, J. and Black Brown, P.".</li>
+ * </ul>
+ *
+ * @param abbreviate
+ * whether to abbreivate first names.
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastFirst(boolean abbreviate, boolean oxfordComma) {
+ int abbrInt = (abbreviate ? 0 : 1);
+ abbrInt += (oxfordComma ? 0 : 2);
+
+ // Check if we've computed this before:
+ if (authorsLastFirst[abbrInt] != null)
+ return authorsLastFirst[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastFirst(abbreviate));
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ }
+ }
+ authorsLastFirst[abbrInt] = res.toString();
+ return authorsLastFirst[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by "and"s with first names after
+ * last name; first names are not abbreviated.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "Smith, John"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "Smith, John and Black
+ * Brown, Peter"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "von
+ * Neumann, John and Smith, John and Black Brown, Peter".</li>
+ * </ul>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsLastFirstAnds(boolean abbreviate) {
+
+ int abbrInt = (abbreviate ? 0 : 1);
+ // Check if we've computed this before:
+ if (authorLastFirstAnds[abbrInt] != null)
+ return authorLastFirstAnds[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getLastFirst(abbreviate));
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getLastFirst(abbreviate));
+ }
+ }
+
+ authorLastFirstAnds[abbrInt] = res.toString();
+ return authorLastFirstAnds[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by commas with first names before
+ * last name; first names are abbreviated or not depending on parameter. If
+ * the list consists of three or more authors, "and" is inserted before the
+ * last author's name.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "John Smith" or "J. Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "John Smith and Peter Black
+ * Brown" or "J. Smith and P. Black Brown"</li>
+ * <li> "John von Neumann and John Smith and Black Brown, Peter" ==> "John
+ * von Neumann, John Smith and Peter Black Brown" or "J. von Neumann, J.
+ * Smith and P. Black Brown" </li>
+ * </ul>
+ *
+ * @param abbr
+ * whether to abbreivate first names.
+ *
+ * @param oxfordComma
+ * Whether to put a comma before the and at the end.
+ *
+ * @see http://en.wikipedia.org/wiki/Serial_comma For an detailed
+ * explaination about the Oxford comma.
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsFirstFirst(boolean abbr, boolean oxfordComma) {
+
+ int abbrInt = (abbr ? 0 : 1);
+ abbrInt += (oxfordComma ? 0 : 2);
+
+ // Check if we've computed this before:
+ if (authorsFirstFirst[abbrInt] != null)
+ return authorsFirstFirst[abbrInt];
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getFirstLast(abbr));
+ int i = 1;
+ while (i < size() - 1) {
+ res.append(", ");
+ res.append(getAuthor(i).getFirstLast(abbr));
+ i++;
+ }
+ if (size() > 2 && oxfordComma)
+ res.append(",");
+ if (size() > 1) {
+ res.append(" and ");
+ res.append(getAuthor(i).getFirstLast(abbr));
+ }
+ }
+ authorsFirstFirst[abbrInt] = res.toString();
+ return authorsFirstFirst[abbrInt];
+ }
+
+ /**
+ * Returns the list of authors separated by "and"s with first names before
+ * last name; first names are not abbreviated.
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "John Smith"</li>
+ * <li>"John Smith and Black Brown, Peter" ==> "John Smith and Peter Black
+ * Brown"</li>
+ * <li>"John von Neumann and John Smith and Black Brown, Peter" ==> "John
+ * von Neumann and John Smith and Peter Black Brown" </li>
+ * </li>
+ *
+ * @return formatted list of authors.
+ */
+ public String getAuthorsFirstFirstAnds() {
+ // Check if we've computed this before:
+ if (authorsFirstFirstAnds != null)
+ return authorsFirstFirstAnds;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getFirstLast(false));
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getFirstLast(false));
+ }
+ }
+ authorsFirstFirstAnds = res.toString();
+ return authorsFirstFirstAnds;
+ }
+
+ /**
+ * Returns the list of authors in a form suitable for alphabetization. This
+ * means that last names come first, never preceded by "von" particles, and
+ * that any braces are removed. First names are abbreviated so the same name
+ * is treated similarly if abbreviated in one case and not in another. This
+ * form is not intended to be suitable for presentation, only for sorting.
+ *
+ * <p>
+ * <ul>
+ * <li>"John Smith" ==> "Smith, J.";</li>
+ *
+ *
+ * @return formatted list of authors
+ */
+ public String getAuthorsForAlphabetization() {
+ if (authorsAlph != null)
+ return authorsAlph;
+
+ StringBuffer res = new StringBuffer();
+ if (size() > 0) {
+ res.append(getAuthor(0).getNameForAlphabetization());
+ for (int i = 1; i < size(); i++) {
+ res.append(" and ");
+ res.append(getAuthor(i).getNameForAlphabetization());
+ }
+ }
+ authorsAlph = res.toString();
+ return authorsAlph;
+ }
+
+ /**
+ * This is an immutable class that keeps information regarding single
+ * author. It is just a container for the information, with very simple
+ * methods to access it.
+ * <p>
+ * Current usage: only methods <code>getLastOnly</code>,
+ * <code>getFirstLast</code>, and <code>getLastFirst</code> are used;
+ * all other methods are provided for completeness.
+ */
+ public static class Author {
+ private final String first_part;
+
+ private final String first_abbr;
+
+ private final String von_part;
+
+ private final String last_part;
+
+ private final String jr_part;
+
+ /**
+ * Creates the Author object. If any part of the name is absent, <CODE>null</CODE>
+ * must be passes; otherwise other methods may return erroneous results.
+ *
+ * @param first
+ * the first name of the author (may consist of several
+ * tokens, like "Charles Louis Xavier Joseph" in "Charles
+ * Louis Xavier Joseph de la Vall{\'e}e Poussin")
+ * @param firstabbr
+ * the abbreviated first name of the author (may consist of
+ * several tokens, like "C. L. X. J." in "Charles Louis
+ * Xavier Joseph de la Vall{\'e}e Poussin"). It is a
+ * responsibility of the caller to create a reasonable
+ * abbreviation of the first name.
+ * @param von
+ * the von part of the author's name (may consist of several
+ * tokens, like "de la" in "Charles Louis Xavier Joseph de la
+ * Vall{\'e}e Poussin")
+ * @param last
+ * the lats name of the author (may consist of several
+ * tokens, like "Vall{\'e}e Poussin" in "Charles Louis Xavier
+ * Joseph de la Vall{\'e}e Poussin")
+ * @param jr
+ * the junior part of the author's name (may consist of
+ * several tokens, like "Jr. III" in "Smith, Jr. III, John")
+ */
+ public Author(String first, String firstabbr, String von, String last, String jr) {
+ first_part = first;
+ first_abbr = firstabbr;
+ von_part = von;
+ last_part = last;
+ jr_part = jr;
+ }
+
+ /**
+ * Returns the first name of the author stored in this object ("First").
+ *
+ * @return first name of the author (may consist of several tokens)
+ */
+ public String getFirst() {
+ return first_part;
+ }
+
+ /**
+ * Returns the abbreviated first name of the author stored in this
+ * object ("F.").
+ *
+ * @return abbreviated first name of the author (may consist of several
+ * tokens)
+ */
+ public String getFirstAbbr() {
+ return first_abbr;
+ }
+
+ /**
+ * Returns the von part of the author's name stored in this object
+ * ("von").
+ *
+ * @return von part of the author's name (may consist of several tokens)
+ */
+ public String getVon() {
+ return von_part;
+ }
+
+ /**
+ * Returns the last name of the author stored in this object ("Last").
+ *
+ * @return last name of the author (may consist of several tokens)
+ */
+ public String getLast() {
+ return last_part;
+ }
+
+ /**
+ * Returns the junior part of the author's name stored in this object
+ * ("Jr").
+ *
+ * @return junior part of the author's name (may consist of several
+ * tokens) or null if the author does not have a Jr. Part
+ */
+ public String getJr() {
+ return jr_part;
+ }
+
+ /**
+ * Returns von-part followed by last name ("von Last"). If both fields
+ * were specified as <CODE>null</CODE>, the empty string <CODE>""</CODE>
+ * is returned.
+ *
+ * @return 'von Last'
+ */
+ public String getLastOnly() {
+ if (von_part == null) {
+ return (last_part == null ? "" : last_part);
+ } else {
+ return (last_part == null ? von_part : von_part + " " + last_part);
+ }
+ }
+
+ /**
+ * Returns the author's name in form 'von Last, Jr., First' with the
+ * first name full or abbreviated depending on parameter.
+ *
+ * @param abbr
+ * <CODE>true</CODE> - abbreviate first name, <CODE>false</CODE> -
+ * do not abbreviate
+ * @return 'von Last, Jr., First' (if <CODE>abbr==false</CODE>) or
+ * 'von Last, Jr., F.' (if <CODE>abbr==true</CODE>)
+ */
+ public String getLastFirst(boolean abbr) {
+ String res = getLastOnly();
+ if (jr_part != null)
+ res += ", " + jr_part;
+ if (abbr) {
+ if (first_abbr != null)
+ res += ", " + first_abbr;
+ } else {
+ if (first_part != null)
+ res += ", " + first_part;
+ }
+ return res;
+ }
+
+ /**
+ * Returns the author's name in form 'First von Last, Jr.' with the
+ * first name full or abbreviated depending on parameter.
+ *
+ * @param abbr
+ * <CODE>true</CODE> - abbreviate first name, <CODE>false</CODE> -
+ * do not abbreviate
+ * @return 'First von Last, Jr.' (if <CODE>abbr==false</CODE>) or 'F.
+ * von Last, Jr.' (if <CODE>abbr==true</CODE>)
+ */
+ public String getFirstLast(boolean abbr) {
+ String res = getLastOnly();
+ if (abbr) {
+ res = (first_abbr == null ? "" : first_abbr + " ") + res;
+ } else {
+ res = (first_part == null ? "" : first_part + " ") + res;
+ }
+ if (jr_part != null)
+ res += ", " + jr_part;
+ return res;
+ }
+
+ /**
+ * Returns the name as "Last, Jr, F." omitting the von-part and removing
+ * starting braces.
+ *
+ * @return "Last, Jr, F." as described above or "" if all these parts
+ * are empty.
+ */
+ public String getNameForAlphabetization() {
+ StringBuffer res = new StringBuffer();
+ if (last_part != null)
+ res.append(last_part);
+ if (jr_part != null) {
+ res.append(", ");
+ res.append(jr_part);
+ }
+ if (first_abbr != null) {
+ res.append(", ");
+ res.append(first_abbr);
+ }
+ while ((res.length() > 0) && (res.charAt(0) == '{'))
+ res.deleteCharAt(0);
+ return res.toString();
+ }
+ }// end Author
+}// end AuthorList
package net.sf.jabref;
-import java.awt.*;
-import java.awt.datatransfer.*;
-import java.awt.event.*;
-import java.io.*;
-import java.util.*;
-import java.util.List;
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.ClipboardOwner;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
import java.nio.charset.UnsupportedCharsetException;
-import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JFileChooser;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JSplitPane;
+import javax.swing.JTextArea;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.filechooser.FileFilter;
import javax.swing.tree.TreePath;
-import javax.swing.undo.*;
-import net.sf.jabref.collab.*;
+import javax.swing.undo.CannotRedoException;
+import javax.swing.undo.CannotUndoException;
+
+import net.sf.jabref.collab.ChangeScanner;
+import net.sf.jabref.collab.FileUpdateListener;
+import net.sf.jabref.collab.FileUpdatePanel;
import net.sf.jabref.export.*;
import net.sf.jabref.external.AutoSetExternalFileForEntries;
-import net.sf.jabref.groups.*;
-import net.sf.jabref.imports.*;
-import net.sf.jabref.labelPattern.LabelPatternUtil;
-import net.sf.jabref.undo.*;
-import net.sf.jabref.wizard.text.gui.TextInputDialog;
+import net.sf.jabref.external.WriteXMPAction;
+import net.sf.jabref.groups.GroupSelector;
+import net.sf.jabref.groups.GroupTreeNode;
+import net.sf.jabref.gui.GlazedEntrySorter;
+import net.sf.jabref.gui.MainTable;
+import net.sf.jabref.gui.MainTableFormat;
+import net.sf.jabref.gui.MainTableSelectionListener;
+import net.sf.jabref.imports.AppendDatabaseAction;
+import net.sf.jabref.imports.BibtexParser;
import net.sf.jabref.journals.AbbreviateAction;
import net.sf.jabref.journals.UnabbreviateAction;
-import net.sf.jabref.gui.*;
+import net.sf.jabref.labelPattern.LabelPatternUtil;
import net.sf.jabref.search.NoSearchMatcher;
import net.sf.jabref.search.SearchMatcher;
-import com.jgoodies.uif_lite.component.UIFSplitPane;
-import com.jgoodies.forms.builder.DefaultFormBuilder;
-import com.jgoodies.forms.layout.FormLayout;
+import net.sf.jabref.undo.CountingUndoManager;
+import net.sf.jabref.undo.NamedCompound;
+import net.sf.jabref.undo.UndoableChangeType;
+import net.sf.jabref.undo.UndoableInsertEntry;
+import net.sf.jabref.undo.UndoableKeyChange;
+import net.sf.jabref.undo.UndoableRemoveEntry;
+import net.sf.jabref.wizard.text.gui.TextInputDialog;
import ca.odell.glazedlists.FilterList;
-import ca.odell.glazedlists.matchers.Matcher;
-import ca.odell.glazedlists.event.ListEventListener;
import ca.odell.glazedlists.event.ListEvent;
+import ca.odell.glazedlists.event.ListEventListener;
+import ca.odell.glazedlists.matchers.Matcher;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+import com.jgoodies.uif_lite.component.UIFSplitPane;
public class BasePanel extends JPanel implements ClipboardOwner, FileUpdateListener {
private EntryEditor currentEditor = null;
private PreviewPanel currentPreview = null;
- boolean tmp = true;
+ boolean tmp = true;
private MainTableSelectionListener selectionListener = null;
private ListEventListener groupsHighlightListener;
JabRefFrame frame;
BibtexDatabase database;
// The database shown in this panel.
- File file = null,
- fileToOpen = null; // The filename of the database.
+
+ // Moving file to MetaData (Morten, 2006.08.29)
+ // private File fileToOpen = null;
+
String fileMonitorHandle = null;
boolean saving = false, updatedExternally = false;
private String encoding;
db.setCompleters(autoCompleters);
}*/
- this.file = file;
+ metaData.setFile(file);
// Register so we get notifications about outside changes to the file.
if (file != null)
}
}
+ public boolean isBaseChanged(){
+ return baseChanged;
+ }
+
public int getMode() {
return mode;
}
- public BibtexDatabase database() { return database; }
- public MetaData metaData() { return metaData; }
- public File file() { return file; }
- public JabRefFrame frame() { return frame; }
- public JabRefPreferences prefs() { return Globals.prefs; }
+ public BibtexDatabase database() {
+ return database;
+ }
- public String getEncoding() { return encoding; }
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
+ public MetaData metaData() {
+ return metaData;
+ }
+
+ public JabRefFrame frame() {
+ return frame;
+ }
+
+ public JabRefPreferences prefs() {
+ return Globals.prefs;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
public void output(String s) {
//Util.pr("\""+s+"\""+(SwingUtilities.isEventDispatchThread()));
actions.put("test", new BaseAction () {
public void action() throws Throwable {
+ ExportFormats.initAllExports();
+ JFileChooser fc = ExportFormats.createExportFileChooser("/home/alver/Documents");
+ fc.showSaveDialog(frame);
+ File file = fc.getSelectedFile();
+ if (file == null)
+ return;
+ FileFilter ff = fc.getFileFilter();
+ if (ff instanceof ExportFileFilter) {
+ ExportFormat format = ((ExportFileFilter)ff).getExportFormat();
+ format.performExport(database, file.getPath(), "UTF8", null);
+ // Make sure we remember which filter was used, to set the default
+ // for next time:
+ Globals.prefs.put("lastUsedExport", format.getConsoleName());
-
+ }
}
});
public void init() throws Throwable {
success = false;
cancelled = false;
- if (file == null)
+ if (getFile() == null)
runCommand("saveAs");
else {
else if (answer == JOptionPane.YES_OPTION) {
ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this); //, panel.database(), panel.metaData());
//try {
- scanner.changeScan(file());
+ scanner.changeScan(getFile());
setUpdatedExternally(false);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
- sidePaneManager.hideAway("fileUpdate");
+ sidePaneManager.hide("fileUpdate");
}
});
public void update() {
if (success) {
- frame.setTabTitle(BasePanel.this, file.getName());
+ // Reset title of tab
+ frame.setTabTitle(BasePanel.this, getFile().getName(),
+ getFile().getAbsolutePath());
frame.output(Globals.lang("Saved database")+" '"
- +file.getPath()+"'.");
+ +getFile().getPath()+"'.");
} else if (!cancelled) {
frame.output(Globals.lang("Save failed"));
}
}
public void run() {
- if (file == null) {
+ if (getFile() == null) {
cancelled = true;
return;
}
}
// Done with autosetting keys. Now save the database:
- success = saveDatabase(file, false, encoding);
+ success = saveDatabase(getFile(), false, encoding);
//Util.pr("Testing resolve string... BasePanel line 237");
//Util.pr("Resolve aq: "+database.resolveString("aq"));
JFileChooser.SAVE_DIALOG, false);
if (chosenFile != null) {
- file = new File(chosenFile);
- if (!file.exists() ||
+ metaData.setFile(new File(chosenFile));
+ if (!metaData.getFile().exists() ||
(JOptionPane.showConfirmDialog
- (frame, "'"+file.getName()+"' "+Globals.lang("exists. Overwrite file?"),
+ (frame, "'"+metaData.getFile().getName()+"' "+Globals.lang("exists. Overwrite file?"),
Globals.lang("Save database"), JOptionPane.OK_CANCEL_OPTION)
== JOptionPane.OK_OPTION)) {
// Register so we get notifications about outside changes to the file.
try {
- fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(BasePanel.this,file);
+ fileMonitorHandle = Globals.fileUpdateMonitor.addUpdateListener(BasePanel.this,getFile());
} catch (IOException ex) {
ex.printStackTrace();
}
- Globals.prefs.put("workingDirectory", file.getParent());
- frame.getFileHistory().newFile(file.getPath());
+ Globals.prefs.put("workingDirectory", metaData.getFile().getParent());
+ frame.getFileHistory().newFile(metaData.getFile().getPath());
}
- else
- file = null;
+ else {
+ metaData.setFile(null);
}
+ }
}
});
// The action for toggling the groups interface
actions.put("toggleGroups", new BaseAction() {
public void action() {
- sidePaneManager.togglePanel("groups");
- frame.groupToggle.setSelected(sidePaneManager.isPanelVisible("groups"));
+ sidePaneManager.toggle("groups");
+ frame.groupToggle.setSelected(sidePaneManager.isComponentVisible("groups"));
}
});
actions.put("search", new BaseAction() {
public void action() {
//sidePaneManager.togglePanel("search");
- sidePaneManager.ensureVisible("search");
+ sidePaneManager.show("search");
//boolean on = sidePaneManager.isPanelVisible("search");
frame.searchToggle.setSelected(true);
if (true)
actions.put("toggleSearch", new BaseAction() {
public void action() {
//sidePaneManager.togglePanel("search");
- sidePaneManager.togglePanel("search");
- boolean on = sidePaneManager.isPanelVisible("search");
+ sidePaneManager.toggle("search");
+ boolean on = sidePaneManager.isComponentVisible("search");
frame.searchToggle.setSelected(on);
if (on)
frame.searchManager.startSearch();
actions.put("incSearch", new BaseAction() {
public void action() {
- sidePaneManager.ensureVisible("search");
+ sidePaneManager.show("search");
frame.searchToggle.setSelected(true);
frame.searchManager.startIncrementalSearch();
}
actions.put("mergeDatabase", new AppendDatabaseAction(frame, this));
+
+
+
+
actions.put("openFile", new BaseAction() {
public void action() {
(new Thread() {
try {
BibtexEntry[] bes = mainTable.getSelectedEntries();
StringWriter sw = new StringWriter();
- FileActions.exportEntries(database, bes, format, custom, directory, sw);
+ System.out.println("actual export to clipboard not implemented...");
+ //FileActions.exportEntries(database, bes, format, custom, directory, sw);
ClipboardOwner owner = new ClipboardOwner() {
public void lostOwnership(Clipboard clipboard, Transferable content) {}
};
});
-
-
+ actions.put("writeXMP", new WriteXMPAction(this));
+
actions.put("abbreviateIso", new AbbreviateAction(this, true));
actions.put("abbreviateMedline", new AbbreviateAction(this, false));
actions.put("unabbreviate", new UnabbreviateAction(this));
* prompted for an entry type.
*
* @param type The type of the entry to create.
+ * @return The newly created BibtexEntry or null the operation was canceled by the user.
*/
- public void newEntry(BibtexEntryType type) {
+ public BibtexEntry newEntry(BibtexEntryType type) {
if (type == null) {
// Find out what type is wanted.
EntryTypeDialog etd = new EntryTypeDialog(frame);
markBaseChanged(); // The database just changed.
new FocusRequester(getEntryEditor(be));
+ return be;
} catch (KeyCollisionException ex) {
Util.pr(ex.getMessage());
}
}
+ return null;
}
MainTableFormat tableFormat = new MainTableFormat(this);
tableFormat.updateTableFormat();
//EventTableModel tableModel = new EventTableModel(sortedList, tableFormat);
- mainTable = new MainTable(/*tableModel, */tableFormat, searchFilterList, frame);
+ mainTable = new MainTable(/*tableModel, */tableFormat, searchFilterList, frame, this);
selectionListener = new MainTableSelectionListener(this, mainTable);
mainTable.updateFont();
mainTable.addSelectionListener(selectionListener);
mainTable.addMouseListener(selectionListener);
-
+ mainTable.addKeyListener(selectionListener);
+ mainTable.addFocusListener(selectionListener);
+
// Add the listener that will take care of highlighting groups as the selection changes:
groupsHighlightListener = new ListEventListener() {
public void listChanged(ListEvent listEvent) {
// database has changed.
String oldTitle = frame.getTabTitle(this);
if (!oldTitle.endsWith("*"))
- frame.setTabTitle(this, oldTitle+"*");
+ frame.setTabTitle(this, oldTitle+"*", frame.getTabTooltip(this));
// If the status line states that the base has been saved, we
// remove this message, since it is no longer relevant. If a
}
else if (baseChanged && !nonUndoableChange) {
baseChanged = false;
- if (file != null)
- frame.setTabTitle(BasePanel.this, file.getName());
+ if (getFile() != null)
+ frame.setTabTitle(BasePanel.this, getFile().getName(),
+ getFile().getAbsolutePath());
else
- frame.setTabTitle(BasePanel.this, Globals.lang("untitled"));
+ frame.setTabTitle(BasePanel.this, Globals.lang("untitled"), null);
}
}
public void run() {
// Test: running scan automatically in background
ChangeScanner scanner = new ChangeScanner(frame, BasePanel.this);
- scanner.changeScan(BasePanel.this.file());
+ scanner.changeScan(BasePanel.this.getFile());
try {
scanner.join();
} catch (InterruptedException e) {
}
if (scanner.changesFound()) {
- FileUpdatePanel pan = new FileUpdatePanel(frame, BasePanel.this, sidePaneManager, file, scanner);
- sidePaneManager.add("fileUpdate", pan);
+ FileUpdatePanel pan = new FileUpdatePanel(frame, BasePanel.this,
+ sidePaneManager, getFile(), scanner);
+ sidePaneManager.register("fileUpdate", pan);
+ sidePaneManager.show("fileUpdate");
setUpdatedExternally(false);
//scanner.displayResult();
} else {
}
public void fileRemoved() {
- Util.pr("File '"+file.getPath()+"' has been deleted.");
+ Util.pr("File '"+getFile().getPath()+"' has been deleted.");
}
return mainTable.getSelectedEntries();
}
+ /**
+ * Get the file where this database was last saved to or loaded from, if any.
+ *
+ * @return The relevant File, or null if none is defined.
+ */
+ public File getFile() {
+ return metaData.getFile();
+ }
+
/**
* Get a String containing a comma-separated list of the bibtex keys
* of the selected entries.
return frame.groupSelector;
}
-}
+}
\ No newline at end of file
* be used for entries that are being displayed in the GUI. Furthermore, it
* does not check values for content, so e.g. empty strings will be set as such.
*/
- public void setField(HashMap fields){
+ public void setField(Map fields){
_fields.putAll(fields);
}
+ /**
+ * Set a field, and notify listeners about the change.
+ *
+ * @param name The field to set.
+ * @param value The value to set.
+ */
public void setField(String name, Object value) {
if (ID_FIELD.equals(name)) {
Object oldValue = _fields.get(name);
try {
- /* The first event is no longer needed, so the following comment doesn't apply
- as of 2005.08.11.
-
- // First throw an empty event that just signals that this entry
- // is about to change. This is needed, so the EntrySorter can
- // remove the entry from its TreeSet. After a sort-sensitive
- // field changes, the entry will not be found by the TreeMap,
- // so without this event it would be impossible to reinsert this
- // entry to keep everything sorted properly.
- firePropertyChangedEvent(null, null, null);
- */
-
// We set the field before throwing the changeEvent, to enable
- // the change listener to access the new value if the change
- // sets off a change in database sorting etc.
- _fields.put(name, value);
+ // the change listener to access the new value if the change
+ // sets off a change in database sorting etc.
+ _fields.put(name, value);
firePropertyChangedEvent(name, oldValue, value);
} catch (PropertyVetoException pve) {
- // Since we have already made the change, we must undo it since
- // the change was rejected:
- _fields.put(name, oldValue);
+ // Since we have already made the change, we must undo it since
+ // the change was rejected:
+ _fields.put(name, oldValue);
throw new IllegalArgumentException("Change rejected: " + pve);
}
}
/**
- * Removes the mapping for the field name.
+ * Remove the mapping for the field name, and notify listeners about
+ * the change.
+ *
+ * @param name The field to clear.
*/
public void clearField(String name) {
Object oldValue = _fields.get(name);
_fields.remove(name);
try {
- firePropertyChangedEvent(name, oldValue, "");
+ firePropertyChangedEvent(name, oldValue, null);
} catch (PropertyVetoException pve) {
throw new IllegalArgumentException("Change rejected: " + pve);
}
return text;
return text.substring(0, maxCharacters + 1) + "...";
}
+
}
} else {
String ours = ((String) f1).toLowerCase(),
theirs = ((String) f2).toLowerCase();
- System.out.println(ours);
int comp = ours.compareTo(theirs);
result = -comp;
}
import net.sf.jabref.external.ExternalFilePanel;
import net.sf.jabref.journals.JournalAbbreviations;
import net.sf.jabref.gui.date.*;
-
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+/**
+ * GUI component that allows editing of the fields of a BibtexEntry. EntryEditor
+ * also registers itself as a VetoableChangeListener, receiving events whenever
+ * a field of the entry changes, enabling the text fields to update themselves
+ * if the change is made from somewhere else.
+ */
public class EntryEditor extends JPanel implements VetoableChangeListener {
- /*
- * GUI component that allows editing of the fields of a BibtexEntry.
- * EntryTypeForm also registers itself as a VetoableChangeListener, receiving
- * events whenever a field of the entry changes, enabling the text fields to
- * update themselves if the change is made from somewhere else.
- */
-
- // A reference to the entry this object works on.
- private BibtexEntry entry;
- BibtexEntryType type;
- CloseAction closeAction;
-
- // The action concerned with closing the window.
- DeleteAction deleteAction = new DeleteAction();
-
- // The action that deletes the current entry, and closes the editor.
- CopyKeyAction copyKeyAction;
-
- // The action concerned with copying the BibTeX key to the clipboard.
- AbstractAction nextEntryAction = new NextEntryAction();
-
- // The action concerned with copying the BibTeX key to the clipboard.
- AbstractAction prevEntryAction = new PrevEntryAction();
-
- // Actions for switching to next/previous entry.
- public StoreFieldAction storeFieldAction;
-
- // The action concerned with storing a field value.
- SwitchLeftAction switchLeftAction = new SwitchLeftAction();
- SwitchRightAction switchRightAction = new SwitchRightAction();
-
- // The actions concerned with switching the panels.
- GenerateKeyAction generateKeyAction;
-
- // The action which generates a bibtexkey for this entry.
- SaveDatabaseAction saveDatabaseAction = new SaveDatabaseAction();
- JPanel mainPanel = new JPanel();
- JPanel srcPanel = new JPanel();
- EntryEditorTab genPan, optPan, reqPan, absPan;
-
- JTextField bibtexKey;
- FieldTextField tf;
- JTextArea source;
- JToolBar tlb;
- JTabbedPane tabbed = new JTabbedPane(); //JTabbedPane.RIGHT);
- GridBagLayout gbl = new GridBagLayout();
- GridBagConstraints con;
- JLabel lab;
- TypeLabel typeLabel;
- JabRefFrame frame;
- BasePanel panel;
- EntryEditor ths = this;
- HashSet contentSelectors = new HashSet();
- Logger logger = Logger.getLogger(EntryEditor.class.getName());
- boolean updateSource = true; // This can be set to false to stop the source
-
- List tabs = new ArrayList();
-
- // text area from gettin updated. This is used in cases where the source
- // couldn't be parsed, and the user is given the option to edit it.
- boolean lastSourceAccepted = true; // This indicates whether the last
-
- // attempt
- // at parsing the source was successful. It is used to determine whether the
- // dialog should close; it should stay open if the user received an error
- // message about the source, whatever he or she chose to do about it.
- String lastSourceStringAccepted = null; // This is used to prevent double
-
-
- // fields.
- // These values can be used to calculate the preferred height for the form.
- // reqW starts at 1 because it needs room for the bibtex key field.
- private int sourceIndex = -1; // The index the source panel has in tabbed.
-
- //private final int REQ=0, OPT=1, GEN=2, FIELD_WIDTH=40, FIELD_HEIGHT=2;
- private final String KEY_PROPERTY = "bibtexkey";
- JabRefPreferences prefs;
- HelpAction helpAction;
- UndoAction undoAction = new UndoAction();
- RedoAction redoAction = new RedoAction();
- TabListener tabListener = new TabListener();
-
- public EntryEditor(JabRefFrame frame_, BasePanel panel_, BibtexEntry entry_) {
-
- frame = frame_;
- panel = panel_;
- entry = entry_;
- prefs = Globals.prefs;
- type = entry.getType();
-
-
- entry.addPropertyChangeListener(this);
-
- helpAction = new HelpAction(frame.helpDiag, GUIGlobals.entryEditorHelp, "Help");
- closeAction = new CloseAction();
- copyKeyAction = new CopyKeyAction();
- generateKeyAction = new GenerateKeyAction(frame);
- storeFieldAction = new StoreFieldAction();
-
- BorderLayout bl = new BorderLayout();
- setLayout(bl);
- setupToolBar();
- setupFieldPanels();
- setupSourcePanel();
- add(tabbed, BorderLayout.CENTER);
- tabbed.addChangeListener(tabListener);
- if (prefs.getBoolean("showSource") && prefs.getBoolean("defaultShowSource"))
- tabbed.setSelectedIndex(sourceIndex);
-
- updateAllFields();
- }
-
- private void setupFieldPanels() {
- tabbed.removeAll();
- tabs.clear();
- String[] fields = entry.getRequiredFields();
-
-
- List fieldList = null;
- if (fields != null)
- fieldList = java.util.Arrays.asList(fields);
- reqPan = new EntryEditorTab(fieldList, this, true, Globals.lang("Required fields"));
- tabbed.addTab(Globals.lang("Required fields"),
- GUIGlobals.getImage("required"), reqPan.getPane(),
- Globals.lang("Show required fields"));
- tabs.add(reqPan);
- //}
-
- if ((entry.getOptionalFields() != null) && (entry.getOptionalFields().length >= 1)) {
- optPan = new EntryEditorTab(java.util.Arrays.asList(entry.getOptionalFields()),
- this, false, Globals.lang("Optional fields"));
- tabbed.addTab(Globals.lang("Optional fields"),
- GUIGlobals.getImage("optional"), optPan.getPane(),
- Globals.lang("Show optional fields"));
- tabs.add(optPan);
- }
-
- EntryEditorTabList tabList = Globals.prefs.getEntryEditorTabList();
- for (int i=0; i<tabList.getTabCount(); i++) {
- EntryEditorTab newTab = new EntryEditorTab(tabList.getTabFields(i),
- this, false, tabList.getTabName(i));
- tabbed.addTab(tabList.getTabName(i), GUIGlobals.getImage("general"), newTab.getPane());
- tabs.add(newTab);
- }
-
- srcPanel.setName(Globals.lang("BibTeX source"));
- if (Globals.prefs.getBoolean("showSource")) {
- tabbed.addTab(Globals.lang("BibTeX source"),
- GUIGlobals.getImage("source"), srcPanel,
- Globals.lang("Show/edit BibTeX source"));
- tabs.add(srcPanel);
- }
- sourceIndex = tabs.size() - 1; // Set the sourceIndex variable.
- srcPanel.setFocusCycleRoot(true);
- }
-
- public BibtexEntryType getType() {
- return type;
- }
-
-
- public BibtexEntry getEntry() {
- return entry;
- }
-
- private void setupToolBar() {
- tlb = new JToolBar(JToolBar.VERTICAL);
-
- //tlb.setMargin(new Insets(2,2,2,2));
- tlb.setMargin(new Insets(0, 0, 0, 2));
-
- // The toolbar carries all the key bindings that are valid for the whole
- // window.
- //tlb.setBackground(GUIGlobals.lightGray);//Color.white);
- ActionMap am = tlb.getActionMap();
- InputMap im = tlb.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
-
- im.put(prefs.getKey("Close entry editor"), "close");
- am.put("close", closeAction);
- im.put(prefs.getKey("Entry editor, store field"), "store");
- am.put("store", storeFieldAction);
- im.put(prefs.getKey("Autogenerate BibTeX keys"), "generateKey");
- am.put("generateKey", generateKeyAction);
- /*im.put(prefs.getKey("Entry editor, previous panel"), "left");
- im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
- am.put("left", switchLeftAction);
- im.put(prefs.getKey("Entry editor, next panel"), "right");
- im.put(prefs.getKey("Entry editor, next panel 2"), "right");
- am.put("right", switchRightAction);*/
- im.put(prefs.getKey("Entry editor, previous entry"), "prev");
- am.put("prev", prevEntryAction);
- im.put(prefs.getKey("Entry editor, next entry"), "next");
- am.put("next", nextEntryAction);
- im.put(prefs.getKey("Undo"), "undo");
- am.put("undo", undoAction);
- im.put(prefs.getKey("Redo"), "redo");
- am.put("redo", redoAction);
- im.put(prefs.getKey("Help"), "help");
- am.put("help", helpAction);
-
- tlb.setFloatable(false);
- tlb.add(closeAction);
-
- setLabel();
- tlb.add(typeLabel);
-
- //tlb.addSeparator();
- //tlb.add(copyKeyAction);
- tlb.addSeparator();
- tlb.add(generateKeyAction);
- tlb.addSeparator();
-
- //tlb.add(undoAction);
- //tlb.add(redoAction);
- tlb.add(deleteAction);
- tlb.add(prevEntryAction);
-
- tlb.add(nextEntryAction);
- tlb.addSeparator();
- tlb.add(helpAction);
-
- Component[] comps = tlb.getComponents();
-
- for (int i = 0; i < comps.length; i++)
- ((JComponent) comps[i]).setOpaque(false);
-
- add(tlb, BorderLayout.WEST);
- }
-
- private void setLabel() {
- typeLabel = new TypeLabel(entry.getType().getName());
- }
-
- /**
- * Rebuild the field tabs. This is called e.g. when a new content selector has been added.
- */
- public void rebuildPanels() {
- // Remove change listener, because the rebuilding causes meaningless events and trouble:
- tabbed.removeChangeListener(tabListener);
- setupFieldPanels();//reqPanel, optPanel, genPanel, absPanel);
- // Add the change listener again:
- tabbed.addChangeListener(tabListener);
- revalidate();
- repaint();
- }
-
-
- /**
- * getExtra checks the field name against BibtexFields.getFieldExtras(name).
- * If the name has an entry, the proper component to be shown is created and
- * returned. Otherwise, null is returned. In addition, e.g. listeners can be
- * added to the field editor, even if no component is returned.
- *
- * @param string
- * Field name
- * @return Component to show, or null if none.
- */
- public JComponent getExtra(String string, FieldEditor editor) {
- final FieldEditor ed = editor;
-
- // fieldName and parameter string identically ????
- final String fieldName = editor.getFieldName();
-
- String s = BibtexFields.getFieldExtras( string ) ;
-
- // timestamp or a other field with datepicker command
- if ( (fieldName.equals( Globals.prefs.get("timeStampField"))) ||
- ((s != null) && s.equals("datepicker")) )
- {
- // double click AND datefield => insert the current date (today)
- ((JTextArea) ed).addMouseListener(new MouseAdapter(){
- public void mouseClicked(MouseEvent e){
- if(e.getClickCount()==2) // double click
- {
- String date = Util.easyDateFormat();
- ed.setText(date);
- }
- }
- });
-
- // insert a datepicker, if the extras field contains this command
- if ((s != null) && s.equals("datepicker"))
- {
- DatePickerButton datePicker = new DatePickerButton( ed ) ;
- return datePicker.getDatePicker() ;
- }
- }
-
- if ((s != null) && s.equals("external")) {
-
- // Add external viewer listener for "pdf" and "url" fields.
- ((JComponent) editor).addMouseListener(new ExternalViewerListener());
-
- return null;
- }
- else if ((s != null) && s.equals("journalNames")) {
- // Add controls for switching between abbreviated and full journal names.
- // If this field also has a FieldContentSelector, we need to combine these.
- JPanel controls = new JPanel();
- controls.setLayout(new BorderLayout());
- if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX
- + editor.getFieldName()) != null) {
- FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
- panel.metaData, storeFieldAction, false);
- contentSelectors.add(ws);
- controls.add(ws, BorderLayout.NORTH);
- }
- controls.add(JournalAbbreviations.getNameSwitcher(this, editor, panel.undoManager),
- BorderLayout.SOUTH);
- return controls;
- }
- else if (panel.metaData.getData(Globals.SELECTOR_META_PREFIX
- + editor.getFieldName()) != null)
- {
- FieldContentSelector ws = new FieldContentSelector(frame, panel, frame, editor,
- panel.metaData, storeFieldAction, false);
- contentSelectors.add(ws);
-
- return ws;
- } else if ((s != null) && s.equals("browse")) {
- JButton but = new JButton(Globals.lang("Browse"));
- ((JComponent) editor).addMouseListener(new ExternalViewerListener());
-
- //but.setBackground(GUIGlobals.lightGray);
- but.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- String dir = ed.getText();
-
- if (dir.equals(""))
- dir = prefs.get(fieldName + Globals.FILETYPE_PREFS_EXT, "");
-
- String chosenFile =
- Globals.getNewFile(frame, new File(dir), "." + fieldName,
- JFileChooser.OPEN_DIALOG, false);
-
- if (chosenFile != null) {
- File newFile = new File(chosenFile); //chooser.getSelectedFile();
- ed.setText(newFile.getPath());
- prefs.put(fieldName + Globals.FILETYPE_PREFS_EXT, newFile.getPath());
- updateField(ed);
- }
- }
- });
-
- return but;
- //} else if ((s != null) && s.equals("browsePdf")) {
- } else if ((s != null) && (s.equals("browseDoc") || s.equals("browseDocZip"))) {
-
- final String ext = "."+fieldName.toLowerCase();
- final OpenFileFilter off;
- if (s.equals("browseDocZip"))
- off = new OpenFileFilter(new String[] { ext, ext+".gz", ext+".bz2" });
- else
- off = new OpenFileFilter(new String[] { ext });
-
- ExternalFilePanel pan = new ExternalFilePanel(frame, panel.metaData(), this, fieldName, off, ed);
- return pan;
- }
- /*else if ((s != null) && s.equals("browsePs")) {
- ExternalFilePanel pan = new ExternalFilePanel(frame, this, "ps", off, ed);
- return pan;
- }*/
- else if ((s != null) && s.equals("url")) {
- ((JComponent) editor).setDropTarget(new DropTarget((Component) editor,
- DnDConstants.ACTION_NONE, new SimpleUrlDragDrop(editor, storeFieldAction)));
-
- return null;
- }
-
- else
- return null;
- }
-
- private void setupSourcePanel() {
- source =
- new JTextArea() {
- private boolean antialias = Globals.prefs.getBoolean("antialias");
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D)g;
- if (antialias)
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- super.paint(g2);
- }
- };
- con = new GridBagConstraints();
- con.insets = new Insets(10, 10, 10, 10);
- con.fill = GridBagConstraints.BOTH;
- con.gridwidth = GridBagConstraints.REMAINDER;
- con.gridheight = GridBagConstraints.REMAINDER;
- con.weightx = 1;
- con.weighty = 1;
- srcPanel.setLayout(gbl);
- source.setEditable(true); //prefs.getBoolean("enableSourceEditing"));
- source.setLineWrap(true);
- source.setTabSize(GUIGlobals.INDENT);
- source.addFocusListener(new FieldEditorFocusListener());
- // Add the global focus listener, so a menu item can see if this field
- // was focused when
- // an action was called.
- source.addFocusListener(Globals.focusListener);
- source.setFont(new Font("Monospaced", Font.PLAIN, Globals.prefs.getInt("fontSize")));
- setupJTextComponent(source);
- updateSource();
-
- JScrollPane sp =
- new JScrollPane(source, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
- JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
- gbl.setConstraints(sp, con);
- srcPanel.add(sp);
- }
-
- public void updateSource() {
- if (updateSource) {
- StringWriter sw = new StringWriter(200);
-
- try {
- entry.write(sw, new net.sf.jabref.export.LatexFieldFormatter(), false);
-
- String srcString = sw.getBuffer().toString();
- source.setText(srcString);
- lastSourceStringAccepted = srcString;
- } catch (IOException ex) {
- source.setText("Error: " + ex.getMessage() + "\n\n" + "Correct the entry, and "
- + "reopen editor to display/edit source.");
- source.setEditable(false);
- }
- }
- }
-
- public void setupJTextComponent(JTextComponent ta) {
-
- /*
- * NOTE: This method is only used for the source panel, not for the other tabs. Look at
- * EntryEditorTab for the setup of text components in the other tabs.
- */
-
- /*
- * if ((ta instanceof FieldTextArea) && (prefs.getBoolean("autoComplete"))) {
- * FieldTextArea fta = (FieldTextArea)ta; Completer comp =
- * baseFrame.getAutoCompleter(fta.getFieldName()); if (comp != null)
- * fta.setAutoComplete(comp); }
- */
-
- // Set up key bindings and focus listener for the FieldEditor.
- InputMap im = ta.getInputMap(JComponent.WHEN_FOCUSED);
- ActionMap am = ta.getActionMap();
-
- //im.put(KeyStroke.getKeyStroke(GUIGlobals.closeKey), "close");
- //am.put("close", closeAction);
- im.put(prefs.getKey("Entry editor, store field"), "store");
- am.put("store", storeFieldAction);
-
- im.put(prefs.getKey("Entry editor, next panel"), "right");
- im.put(prefs.getKey("Entry editor, next panel 2"), "right");
- am.put("right", switchRightAction);
-
- im.put(prefs.getKey("Entry editor, previous panel"), "left");
- im.put(prefs.getKey("Entry editor, previous panel 2"), "left");
- am.put("left", switchLeftAction);
-
- im.put(prefs.getKey("Help"), "help");
- am.put("help", helpAction);
- im.put(prefs.getKey("Save database"), "save");
- am.put("save", saveDatabaseAction);
-
- im.put(Globals.prefs.getKey("Next tab"), "nexttab");
- am.put("nexttab", frame.nextTab);
- im.put(Globals.prefs.getKey("Previous tab"), "prevtab");
- am.put("prevtab", frame.prevTab);
- try {
- HashSet keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(AWTKeyStroke.getAWTKeyStroke("pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, keys);
- keys =
- new HashSet(ta.getFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS));
- keys.clear();
- keys.add(KeyStroke.getKeyStroke("shift pressed TAB"));
- ta.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, keys);
- } catch (Throwable t) {
- System.err.println(t);
- }
-
- ta.addFocusListener(new FieldListener());
- }
-
- public void requestFocus() {
- activateVisible();
- }
-
- private void activateVisible() {
- Object activeTab = tabs.get(tabbed.getSelectedIndex());
-
- if (activeTab instanceof EntryEditorTab)
- ((EntryEditorTab)activeTab).activate();
- else
- new FocusRequester(source);
- //((JComponent)activeTab).requestFocus();
- }
-
- /**
- * Reports the enabled status of the editor, as set by setEnabled()
- */
- public boolean isEnabled() {
- return source.isEnabled();
- }
-
- /**
- * Sets the enabled status of all text fields of the entry editor.
- */
- public void setEnabled(boolean enabled) {
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).setEnabled(enabled);
- }
- }
- source.setEnabled(enabled);
-
- }
-
- /**
- * Centers the given row, and highlights it.
- *
- * @param row
- * an <code>int</code> value
- */
- private void scrollTo(int row) {
- panel.mainTable.setRowSelectionInterval(row, row);
- panel.mainTable.ensureVisible(row);
- }
-
- /**
- * Makes sure the current edit is stored.
- */
- public void storeCurrentEdit() {
- Component comp = Globals.focusListener.getFocused();
- if ((comp instanceof FieldEditor) && this.isAncestorOf(comp)) {
- storeFieldAction.actionPerformed(new ActionEvent(comp, 0, ""));
- }
- }
-
-
- /**
- * Returns the index of the active (visible) panel.
- *
- * @return an <code>int</code> value
- */
- public int getVisiblePanel() {
- return tabbed.getSelectedIndex();
- }
-
- /** Returns the name of the currently selected component. */
- public String getVisiblePanelName() {
- return tabbed.getSelectedComponent().getName();
- }
-
- /**
- * Sets the panel with the given index visible.
- *
- * @param i
- * an <code>int</code> value
- */
- public void setVisiblePanel(int i) {
- tabbed.setSelectedIndex(Math.min(i, tabbed.getTabCount() - 1));
- }
-
- public void setVisiblePanel(String name) {
- for (int i = 0; i < tabbed.getTabCount(); ++i) {
- if (name.equals(tabbed.getComponent(i).getName())) {
- tabbed.setSelectedIndex(i);
- return;
- }
- }
- if (tabbed.getTabCount() > 0)
- tabbed.setSelectedIndex(0);
- }
-
- /**
- * Updates this editor to show the given entry, regardless of type
- * correspondence.
- *
- * @param be
- * a <code>BibtexEntry</code> value
- */
- public synchronized void switchTo(BibtexEntry be) {
- if (entry == be)
- return;
-
- //Util.pr("EntryEditor.switchTo(BibtexEntry): "+entry.getCiteKey());
- //Util.pr("::EntryEditor.switchTo(BibtexEntry): "+this.type.getName());
- storeCurrentEdit();
-
- // Remove this instance as property listener for the entry:
- entry.removePropertyChangeListener(this);
- // Register as property listener for the new entry:
- be.addPropertyChangeListener(this);
-
- entry = be;
-
- updateAllFields();
- validateAllFields();
- updateSource();
- panel.showing = be;
-
- }
-
- /**
- * Returns false if the contents of the source panel has not been validated,
- * true othervise.
- */
- public boolean lastSourceAccepted() {
- //Util.pr("Sourceaccepted ....");
- if (tabbed.getSelectedComponent() == srcPanel)
- storeSource(false);
-
- return lastSourceAccepted;
- }
-
- /*
- * public boolean storeSourceIfNeeded() { if (tabbed.getSelectedIndex() ==
- * sourceIndex) return storeSource(); else return true; }
- */
- public boolean storeSource(boolean showError) {
- // Store edited bibtex code.
- BibtexParser bp = new BibtexParser(new java.io.StringReader(source.getText()));
-
- try {
- BibtexDatabase db = bp.parse().getDatabase();
-
- if (db.getEntryCount() > 1)
- throw new Exception("More than one entry found.");
-
- if (db.getEntryCount() < 1)
- throw new Exception("No entries found.");
-
- NamedCompound compound = new NamedCompound(Globals.lang("source edit"));
- BibtexEntry nu = db.getEntryById((String) db.getKeySet().iterator().next());
- String id = entry.getId();
- String
- //oldKey = entry.getCiteKey(),
- newKey = nu.getCiteKey();
- boolean anyChanged = false;
- boolean duplicateWarning = false;
- boolean emptyWarning = newKey == null || newKey.equals("");
-
- if (panel.database.setCiteKeyForEntry(id, newKey)) {
- duplicateWarning = true;
-
- // First, remove fields that the user have removed.
- }
-
- Object[] fields = entry.getAllFields();
-
- for (int i = 0; i < fields.length; i++) {
- if (BibtexFields.isDisplayableField(fields[i].toString())) {
- if (nu.getField(fields[i].toString()) == null) {
- compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(),
- entry.getField(fields[i].toString()), (Object) null));
- entry.clearField(fields[i].toString());
- anyChanged = true;
- }
- }
- }
-
- // Then set all fields that have been set by the user.
- fields = nu.getAllFields();
-
- for (int i = 0; i < fields.length; i++) {
- if (entry.getField(fields[i].toString()) != nu.getField(fields[i].toString())) {
- String toSet = (String) nu.getField(fields[i].toString());
-
- // Test if the field is legally set.
- (new LatexFieldFormatter()).format(toSet, fields[i].toString());
-
- compound.addEdit(new UndoableFieldChange(entry, fields[i].toString(),
- entry.getField(fields[i].toString()), toSet));
- entry.setField(fields[i].toString(), toSet);
- anyChanged = true;
- }
- }
-
- compound.end();
-
- if (!anyChanged)
- return true;
-
- panel.undoManager.addEdit(compound);
-
- /*
- * if (((oldKey == null) && (newKey != null)) || ((oldKey != null) &&
- * (newKey == null)) || ((oldKey != null) && (newKey != null) &&
- * !oldKey.equals(newKey))) { }
- */
- if (duplicateWarning) {
- warnDuplicateBibtexkey();
- } else if (emptyWarning && showError) {
- warnEmptyBibtexkey();
- } else {
- panel.output(Globals.lang("Stored entry") + ".");
- }
-
- lastSourceStringAccepted = source.getText();
- updateAllFields();
- lastSourceAccepted = true;
- updateSource = true;
-
- // TODO: does updating work properly after source stored?
- // panel.tableModel.remap();
- // panel.entryTable.repaint();
- //panel.refreshTable();
- panel.markBaseChanged();
-
- return true;
- } catch (Throwable ex) {
- //ex.printStackTrace();
- // The source couldn't be parsed, so the user is given an
- // error message, and the choice to keep or revert the contents
- // of the source text field.
- updateSource = false;
- lastSourceAccepted = false;
- tabbed.setSelectedComponent(srcPanel);
-
- if (showError) {
- Object[] options =
- { Globals.lang("Edit"), Globals.lang("Revert to original source") };
-
- int answer =
- JOptionPane.showOptionDialog(frame, "Error: " + ex.getMessage(),
- Globals.lang("Problem with parsing entry"), JOptionPane.YES_NO_OPTION,
- JOptionPane.ERROR_MESSAGE, null, options, options[0]);
-
- if (answer != 0) {
- updateSource = true;
- updateSource();
- }
- }
-
- return false;
- }
- }
-
-
- public void setField(String fieldName, String newFieldData) {
-
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).updateField(fieldName, newFieldData);
- }
- }
-
- }
-
-
- /**
- * Sets all the text areas according to the shown entry.
- */
- public void updateAllFields() {
- //System.out.println("EntryEditor.updateAllFields()");
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).setEntry(entry);
- }
- }
- }
-
- /**
- * Removes the "invalid field" color from all text areas.
- */
- public void validateAllFields() {
- for (Iterator i=tabs.iterator(); i.hasNext();) {
- Object o = i.next();
- if (o instanceof EntryEditorTab) {
- ((EntryEditorTab)o).validateAllFields();
- }
- }
- }
-
- public void updateAllContentSelectors() {
- if (contentSelectors.size() > 0) {
- for (Iterator i = contentSelectors.iterator(); i.hasNext();)
- ((FieldContentSelector) i.next()).updateList();
- }
- }
-
- // Update the JTextArea when a field has changed.
- public void vetoableChange(PropertyChangeEvent e) {
- String newValue = ((e.getNewValue() != null) ? e.getNewValue().toString() : "");
- setField(e.getPropertyName(), newValue);
-
- //Util.pr(e.getPropertyName());
- }
-
-
- public void updateField(final Object source) {
- storeFieldAction.actionPerformed(new ActionEvent(source, 0, ""));
- }
-
- private class TypeLabel extends JPanel {
- private String label;
-
- public TypeLabel(String type) {
- label = type;
- addMouseListener(new MouseAdapter() {
- public void mouseClicked(MouseEvent e) {
- boolean ctrlClick = prefs.getBoolean("ctrlClick");
-
- if ((e.getButton() == MouseEvent.BUTTON3)
- || (ctrlClick && (e.getButton() == MouseEvent.BUTTON1)
- && e.isControlDown())) {
- JPopupMenu typeMenu = new JPopupMenu();
-
- //typeMenu.addSeparator();
- for (Iterator i = BibtexEntryType.ALL_TYPES.keySet().iterator();
- i.hasNext();)
- typeMenu.add(new ChangeTypeAction(BibtexEntryType.getType(
- (String) i.next()), panel));
-
- typeMenu.show(ths, e.getX(), e.getY());
- }
- }
- });
- }
-
- public void paint(Graphics g) {
- Graphics2D g2 = (Graphics2D) g;
- g2.setColor(GUIGlobals.validFieldColor);
- g2.setFont(GUIGlobals.typeNameFont);
-
- FontMetrics fm = g2.getFontMetrics();
- int width = fm.stringWidth(label);
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
- g2.rotate(-Math.PI / 2, 0, 0);
- g2.drawString(label, -width - 7, 28);
- }
- }
-
- class FieldListener extends FocusAdapter {
- /*
- * Focus listener that fires the storeFieldAction when a FieldTextArea loses
- * focus.
- */
- public void focusGained(FocusEvent e) {
- }
-
- public void focusLost(FocusEvent e) {
- //Util.pr("Lost focus "+e.getSource().toString().substring(0,30));
- if (!e.isTemporary())
- updateField(e.getSource());
- }
- }
+ // A reference to the entry this object works on.
+ private BibtexEntry entry;
+ BibtexEntryType type;
- class TabListener implements ChangeListener {
- public void stateChanged(ChangeEvent e) {
+ // The action concerned with closing the window.
+ CloseAction closeAction;
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- activateVisible();
- }
- });
+ // The action that deletes the current entry, and closes the editor.
+ DeleteAction deleteAction = new DeleteAction();
+ // The action concerned with copying the BibTeX key to the clipboard.
+ CopyKeyAction copyKeyAction;
- // After the initial event train has finished, we tell the editor tab to update all
- // its fields. This makes sure they are updated even if the tab we just left contained one
- // or more of the same fields as this one:
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- Object activeTab = tabs.get(tabbed.getSelectedIndex());
- if (activeTab instanceof EntryEditorTab)
- ((EntryEditorTab)activeTab).updateAll();
- }
- });
+ &