pax_global_header 0000666 0000000 0000000 00000000064 14214333047 0014513 g ustar 00root root 0000000 0000000 52 comment=85ffa228bcb091e8bc18ecddb39b89aed4d6c26c
jbibtex-1.0.20/ 0000775 0000000 0000000 00000000000 14214333047 0013222 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/.github/ 0000775 0000000 0000000 00000000000 14214333047 0014562 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/.github/workflows/ 0000775 0000000 0000000 00000000000 14214333047 0016617 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/.github/workflows/maven.yml 0000664 0000000 0000000 00000000770 14214333047 0020454 0 ustar 00root root 0000000 0000000 name: maven
on:
push:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ 8, 9, 10, 11, 12, 13, 14 ]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- uses: actions/cache@v2
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- run: mvn -B package --file pom.xml
jbibtex-1.0.20/LICENSE.txt 0000664 0000000 0000000 00000002733 14214333047 0015052 0 ustar 00root root 0000000 0000000 Copyright (c) 2012, University of Tartu
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the University of Tartu nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jbibtex-1.0.20/README.md 0000664 0000000 0000000 00000010335 14214333047 0014503 0 ustar 00root root 0000000 0000000 JBibTeX [](https://github.com/jbibtex/jbibtex/actions?query=workflow%3A%22maven%22)
=======
Java BibTeX and LaTeX parser and formatter library
# Installation #
The current version of JBibTeX is **1.0.19** (14 July, 2021).
The library JAR file (together with source and javadoc JAR files) is distributed via Maven Central repository:
```xml
org.jbibtex
jbibtex
1.0.19
```
# Usage #
### Parsing BibTeX ###
Typical scenario:
```java
Reader reader = ...
org.jbibtex.BibTeXParser bibtexParser = new org.jbibtex.BibTeXParser();
org.jbibtex.BibTeXDatabase database = bibtexParser.parse(reader);
```
BibTeX parser provides two parsing modes:
* `#parse(Reader)`. Normal mode. The parser stops when an error condition is detected.
* `#parseFully(Reader)`. Error recovery mode. The parser skips an erroneous object definition and continues with the next object definition. The list of error conditions can be accessed via `#getExceptions()`.
BibTeX parser performs automatic string constants and crossref fields resolution. The default behavior is to prohibit unresolved references by throwing an unchecked exception `org.jbibtex.ObjectResolutionException`. The default behavior can be overriden as follows:
```java
org.jbibtex.BibTeXParser bibtexParser = new org.jbibtex.BibTeXParser(){
@Override
public void checkStringResolution(org.jbibtex.Key key, org.jbibtex.BibTeXString string){
if(string == null){
System.err.println("Unresolved string: \"" + key.getValue() + "\"");
}
}
@Override
public void checkCrossReferenceResolution(org.jbibtex.Key key, org.jbibtex.BibTeXEntry entry){
if(entry == null){
System.err.println("Unresolved cross-reference: \"" + key.getValue() + "\"");
}
}
};
```
**Caution**: Prior to JBibTeX version 1.0.12, methods `org.jbibtex.BibTeXParser#parse(java.io.Reader)` and `org.jbibtex.LaTeXParser#parse(java.io.Reader)` may throw error `org.jbibtex.TokenMgrError` if the input contains illegal characters or is otherwise problematic. Library users are advised to surround the affected portions of their code with appropriate try-catch statements. An unhandled `org.jbibtex.TokenMgrError` could terminate the JVM process.
Library users may use class `org.jbibtex.CharacterFilterReader` to skip illegal characters in the input:
```java
Reader reader = ...
org.jbibtex.CharacterFilterReader filterReader = new org.jbibtex.CharacterFilterReader(reader);
bibtexParser.parse(filterReader);
```
### Formatting BibTeX ###
Typical scenario:
```java
Writer writer = ...
org.jbibtex.BibTeXDatabase database = ...
org.jbibtex.BibTeXFormatter bibtexFormatter = new org.jbibtex.BibTeXFormatter();
bibtexFormatter.format(database, writer);
```
### Working with BibTeX databases ###
Iterating over all the BibTeX entries in the BibTeX database and retrieving their title field:
```java
org.jbibtex.BibTeXDatabase database = ...
Map entryMap = database.getEntries();
Collection entries = entryMap.values();
for(org.jbibtex.BibTeXEntry entry : entries){
org.jbibtex.Value value = entry.getField(org.jbibtex.BibTeXEntry.KEY_TITLE);
if(value == null){
continue;
}
// Do something with the title value
}
```
BibTeX entry values could be in LaTeX data format. The easiest way to distinguish between plain text and LaTeX text values is to look for LaTeX special symbols `\` and `{`:
```java
org.jbibtex.Value value = ...
String string = value.toUserString();
if(string.indexOf('\\') > -1 || string.indexOf('{') > -1){
// LaTeX string that needs to be translated to plain text string
} else {
// Plain text string
}
```
### Translating LaTeX strings to plain text strings ###
Typical scenario:
```java
String latexString = ...
org.jbibtex.LaTeXParser latexParser = new org.jbibtex.LaTeXParser();
List latexObjects = latexParser.parse(latexString);
org.jbibtex.LaTeXPrinter latexPrinter = new org.jbibtex.LaTeXPrinter();
String plainTextString = latexPrinter.print(latexObjects);
```
# License #
JBibTeX is licensed under the [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause).
jbibtex-1.0.20/pom.xml 0000664 0000000 0000000 00000011121 14214333047 0014533 0 ustar 00root root 0000000 0000000
4.0.0
org.sonatype.oss
oss-parent
9
org.jbibtex
jbibtex
1.0.20
jar
JBibTeX
Java BibTeX parser and formatter
http://www.jbibtex.org
University of Tartu
http://www.ut.ee/en
New BSD License
http://www.opensource.org/licenses/bsd-license.php
repo
villu.ruusmann
Villu Ruusmann
scm:git:git@github.com:jbibtex/jbibtex.git
scm:git:git@github.com:jbibtex/jbibtex.git
git://github.com/jbibtex/jbibtex.git
1.0.20
GitHub
https://github.com/jbibtex/jbibtex/issues
com.fasterxml.jackson.core
jackson-annotations
[2.8.0, 2.13.2]
provided
com.fasterxml.jackson.core
jackson-databind
[2.8.0, 2.13.2]
test
junit
junit
4.13.2
test
org.apache.maven.plugins
maven-compiler-plugin
3.10.0
1.8
1.8
org.apache.maven.plugins
maven-javadoc-plugin
3.3.2
1.8
none
org.apache.maven.plugins
maven-release-plugin
2.5.3
true
false
org.apache.maven.plugins
maven-surefire-plugin
2.22.2
${jacoco.agent}
false
org.codehaus.mojo
animal-sniffer-maven-plugin
1.21
android-21
process-classes
check
net.sf.androidscents.signature
android-api-level-11
3.0_r2
org.codehaus.mojo
javacc-maven-plugin
2.6
javacc
net.java.dev.javacc
javacc
7.0.10
org.jacoco
jacoco-maven-plugin
0.8.7
pre-unit-test
prepare-agent
jacoco.agent
post-unit-test
prepare-package
report
jbibtex-1.0.20/src/ 0000775 0000000 0000000 00000000000 14214333047 0014011 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/ 0000775 0000000 0000000 00000000000 14214333047 0014735 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/java/ 0000775 0000000 0000000 00000000000 14214333047 0015656 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/java/org/ 0000775 0000000 0000000 00000000000 14214333047 0016445 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/java/org/jbibtex/ 0000775 0000000 0000000 00000000000 14214333047 0020074 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXComment.java 0000664 0000000 0000000 00000000564 14214333047 0023404 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class BibTeXComment extends BibTeXObject {
private StringValue value = null;
BibTeXComment(){
}
public BibTeXComment(StringValue value){
setValue(value);
}
public StringValue getValue(){
return this.value;
}
private void setValue(StringValue value){
this.value = value;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXDatabase.java 0000664 0000000 0000000 00000005174 14214333047 0023510 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class BibTeXDatabase implements Serializable {
private List objects = new ArrayList<>();
private List includes = new ArrayList<>();
private KeyMap strings = new KeyMap<>();
private KeyMap entries = new KeyMap<>();
public void addObject(BibTeXObject object){
boolean success;
if(object instanceof BibTeXInclude){
BibTeXInclude include = (BibTeXInclude)object;
success = this.includes.add(include);
} else
if(object instanceof BibTeXString){
BibTeXString string = (BibTeXString)object;
success = this.strings.putIfMissing(string.getKey(), string);
} else
if(object instanceof BibTeXEntry){
BibTeXEntry entry = (BibTeXEntry)object;
success = this.entries.putIfMissing(entry.getKey(), entry);
} else
{
success = true;
} // End if
if(success){
this.objects.add(object);
}
}
public void removeObject(BibTeXObject object){
boolean success;
if(object instanceof BibTeXInclude){
BibTeXInclude include = (BibTeXInclude)object;
success = this.includes.remove(include);
} else
if(object instanceof BibTeXString){
BibTeXString string = (BibTeXString)object;
success = this.strings.removeIfPresent(string.getKey());
} else
if(object instanceof BibTeXEntry){
BibTeXEntry entry = (BibTeXEntry)object;
success = this.entries.removeIfPresent(entry.getKey());
} else
{
success = true;
} // End if
if(success){
this.objects.remove(object);
}
}
public List getObjects(){
return Collections.unmodifiableList(this.objects);
}
public BibTeXString resolveString(Key key){
BibTeXString string = this.strings.get(key);
if(string == null){
for(BibTeXInclude include : this.includes){
BibTeXDatabase database = include.getDatabase();
string = database.resolveString(key);
if(string != null){
return string;
}
}
}
return string;
}
public Map getStrings(){
return Collections.unmodifiableMap(this.strings);
}
public BibTeXEntry resolveEntry(Key key){
BibTeXEntry entry = this.entries.get(key);
if(entry == null){
for(BibTeXInclude include : this.includes){
BibTeXDatabase database = include.getDatabase();
entry = database.resolveEntry(key);
if(entry != null){
return entry;
}
}
}
return entry;
}
public Map getEntries(){
return Collections.unmodifiableMap(this.entries);
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXEntry.java 0000664 0000000 0000000 00000007452 14214333047 0023106 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.util.Collections;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class BibTeXEntry extends BibTeXObject {
private Key type = null;
private Key key = null;
private KeyMap fields = new KeyMap<>();
BibTeXEntry(){
}
public BibTeXEntry(Key type, Key key){
setType(type);
setKey(key);
}
@JsonIgnore
public BibTeXEntry getCrossReference(){
Value value = this.fields.get(KEY_CROSSREF);
CrossReferenceValue crossRefValue = (CrossReferenceValue)value;
if(crossRefValue != null){
return crossRefValue.getEntry();
}
return null;
}
public Value getField(Key key){
Value value = this.fields.get(key);
if(value == null){
BibTeXEntry entry = getCrossReference();
if(entry != null){
return entry.getField(key);
}
}
return value;
}
public void addField(Key key, Value value){
this.fields.put(key, value);
}
public void addAllFields(Map fields){
this.fields.putAll(fields);
}
public void removeField(Key key){
this.fields.remove(key);
}
public Key getType(){
return this.type;
}
private void setType(Key type){
this.type = type;
}
public Key getKey(){
return this.key;
}
private void setKey(Key key){
this.key = key;
}
public Map getFields(){
return Collections.unmodifiableMap(this.fields);
}
public static final Key TYPE_ARTICLE = new Key("article");
public static final Key TYPE_BOOK = new Key("book");
public static final Key TYPE_BOOKLET = new Key("booklet");
public static final Key TYPE_CONFERENCE = new Key("conference");
public static final Key TYPE_INBOOK = new Key("inbook");
public static final Key TYPE_INCOLLECTION = new Key("incollection");
public static final Key TYPE_INPROCEEDINGS = new Key("inproceedings");
public static final Key TYPE_MANUAL = new Key("manual");
public static final Key TYPE_MASTERSTHESIS = new Key("mastersthesis");
public static final Key TYPE_MISC = new Key("misc");
public static final Key TYPE_PHDTHESIS = new Key("phdthesis");
public static final Key TYPE_PROCEEDINGS = new Key("proceedings");
public static final Key TYPE_TECHREPORT = new Key("techreport");
public static final Key TYPE_UNPUBLISHED = new Key("unpublished");
public static final Key KEY_ADDRESS = new Key("address");
public static final Key KEY_ANNOTE = new Key("annote");
public static final Key KEY_AUTHOR = new Key("author");
public static final Key KEY_BOOKTITLE = new Key("booktitle");
public static final Key KEY_CHAPTER = new Key("chapter");
public static final Key KEY_CROSSREF = new Key("crossref");
public static final Key KEY_DOI = new Key("doi");
public static final Key KEY_EDITION = new Key("edition");
public static final Key KEY_EDITOR = new Key("editor");
public static final Key KEY_EPRINT = new Key("eprint");
public static final Key KEY_HOWPUBLISHED = new Key("howpublished");
public static final Key KEY_INSTITUTION = new Key("institution");
public static final Key KEY_JOURNAL = new Key("journal");
public static final Key KEY_KEY = new Key("key");
public static final Key KEY_MONTH = new Key("month");
public static final Key KEY_NOTE = new Key("note");
public static final Key KEY_NUMBER = new Key("number");
public static final Key KEY_ORGANIZATION = new Key("organization");
public static final Key KEY_PAGES = new Key("pages");
public static final Key KEY_PUBLISHER = new Key("publisher");
public static final Key KEY_SCHOOL = new Key("school");
public static final Key KEY_SERIES = new Key("series");
public static final Key KEY_TITLE = new Key("title");
public static final Key KEY_TYPE = new Key("type");
public static final Key KEY_URL = new Key("url");
public static final Key KEY_VOLUME = new Key("volume");
public static final Key KEY_YEAR = new Key("year");
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXFormatter.java 0000664 0000000 0000000 00000005661 14214333047 0023750 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.IOException;
import java.io.Writer;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class BibTeXFormatter {
private String indent = "\t";
public BibTeXFormatter(){
}
public void format(BibTeXDatabase database, Writer writer) throws IOException {
List objects = database.getObjects();
String separator = "";
for(BibTeXObject object : objects){
writer.write(separator);
if(object instanceof BibTeXComment){
format((BibTeXComment)object, writer);
} else
if(object instanceof BibTeXEntry){
format((BibTeXEntry)object, writer);
} else
if(object instanceof BibTeXInclude){
format((BibTeXInclude)object, writer);
} else
if(object instanceof BibTeXPreamble){
format((BibTeXPreamble)object, writer);
} else
if(object instanceof BibTeXString){
format((BibTeXString)object, writer);
} else
{
throw new IllegalArgumentException();
}
separator = "\n\n";
}
writer.flush();
}
protected void format(BibTeXComment comment, Writer writer) throws IOException {
writer.write("@Comment");
format(comment.getValue(), 1, writer);
}
protected void format(BibTeXEntry entry, Writer writer) throws IOException {
writer.write("@");
format(entry.getType(), writer);
writer.write('{');
format(entry.getKey(), writer);
writer.write(',');
writer.write('\n');
Collection> fields = (entry.getFields()).entrySet();
for(Iterator> it = fields.iterator(); it.hasNext(); ){
Map.Entry field = it.next();
writer.write(getIndent());
format(field.getKey(), writer);
writer.write(" = ");
format(field.getValue(), 2, writer);
if(it.hasNext()){
writer.write(',');
}
writer.write('\n');
}
writer.write('}');
}
protected void format(BibTeXInclude include, Writer writer) throws IOException {
writer.write("@Include");
format(include.getValue(), 1, writer);
}
protected void format(BibTeXPreamble preamble, Writer writer) throws IOException {
writer.write("@Preamble");
writer.write('{');
format(preamble.getValue(), 1, writer);
writer.write('}');
}
protected void format(BibTeXString string, Writer writer) throws IOException {
writer.write("@String");
writer.write('{');
format(string.getKey(), writer);
writer.write(" = ");
format(string.getValue(), 1, writer);
writer.write('}');
}
protected void format(Key key, Writer writer) throws IOException {
String string = key.getValue();
writer.write(string);
}
protected void format(Value value, int level, Writer writer) throws IOException {
String string = StringUtil.addIndent(value.format(), level, getIndent());
writer.write(string);
}
public String getIndent(){
return this.indent;
}
public void setIndent(String indent){
this.indent = indent;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXInclude.java 0000664 0000000 0000000 00000001146 14214333047 0023362 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class BibTeXInclude extends BibTeXObject {
private StringValue value = null;
private BibTeXDatabase database = null;
BibTeXInclude(){
}
public BibTeXInclude(StringValue value, BibTeXDatabase database){
setValue(value);
setDatabase(database);
}
public StringValue getValue(){
return this.value;
}
private void setValue(StringValue value){
this.value = value;
}
public BibTeXDatabase getDatabase(){
return this.database;
}
private void setDatabase(BibTeXDatabase database){
this.database = database;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXObject.java 0000664 0000000 0000000 00000000436 14214333047 0023206 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo (
use = JsonTypeInfo.Id.CLASS
)
abstract
public class BibTeXObject implements Serializable {
BibTeXObject(){
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXPreamble.java 0000664 0000000 0000000 00000000537 14214333047 0023531 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class BibTeXPreamble extends BibTeXObject {
private Value value = null;
BibTeXPreamble(){
}
public BibTeXPreamble(Value value){
setValue(value);
}
public Value getValue(){
return this.value;
}
private void setValue(Value value){
this.value = value;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/BibTeXString.java 0000664 0000000 0000000 00000000755 14214333047 0023252 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class BibTeXString extends BibTeXObject {
private Key key = null;
private Value value = null;
BibTeXString(){
}
public BibTeXString(Key key, Value value){
setKey(key);
setValue(value);
}
public Key getKey(){
return this.key;
}
private void setKey(Key key){
this.key = key;
}
public Value getValue(){
return this.value;
}
private void setValue(Value value){
this.value = value;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/CharacterFilterReader.java 0000664 0000000 0000000 00000003207 14214333047 0025126 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2014 University of Tartu
*/
package org.jbibtex;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
public class CharacterFilterReader extends FilterReader {
public CharacterFilterReader(Reader reader){
super(reader);
}
/**
* @return true If the specified character should be accepted, false otherwise.
*
* @see BibTeXParserTokenManager
* @see LaTeXParserTokenManager
*/
protected boolean accept(char c){
// Whitespace
if(c == '\t' || c == '\n' || c == '\f' || c == '\r' || c == ' '){
return true;
}
// ASCII letters, numbers and control characters
if(c >= '\u0021' && c <= '\u007f'){
return true;
}
// Latin-1 supplement letters
if((c >= '\u00c0' && c <= '\u00d6') || (c >= '\u00d8' && c <= '\u00f6') || (c >= '\u00f8' && c <= '\u00ff')){
return true;
}
// Unicode letters
if((c >= '\u0100' && c <= '\u1fff') || (c == '\u20ac' || c == '\u2122')){
return true;
}
return false;
}
@Override
public int read() throws IOException {
while(true){
int result = super.read();
if(result < 0){
return -1;
}
if(accept((char)result)){
return result;
}
}
}
@Override
public int read(char[] buffer, final int offset, final int length) throws IOException {
int count = super.read(buffer, offset, length);
if(count < 0){
return -1;
}
int readOffset = offset;
int writeOffset = offset;
for(int i = 0; i < count; i++){
char c = buffer[readOffset];
readOffset++;
if(accept(c)){
buffer[writeOffset] = c;
writeOffset++;
}
}
return count - (readOffset - writeOffset);
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/ConcateValue.java 0000664 0000000 0000000 00000001313 14214333047 0023306 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class ConcateValue extends Value {
private Value left = null;
private Value right = null;
ConcateValue(){
}
public ConcateValue(Value left, Value right){
setLeft(left);
setRight(right);
}
@Override
protected String format(){
return getLeft().format() + " # " + getRight().format();
}
@Override
public String toUserString(){
return getLeft().toUserString() + getRight().toUserString();
}
public Value getLeft(){
return this.left;
}
private void setLeft(Value left){
this.left = left;
}
public Value getRight(){
return this.right;
}
private void setRight(Value right){
this.right = right;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/CrossReferenceValue.java 0000664 0000000 0000000 00000001572 14214333047 0024651 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class CrossReferenceValue extends Value implements Resolvable {
private Value value = null;
private BibTeXEntry entry = null;
CrossReferenceValue(){
}
public CrossReferenceValue(Value value, BibTeXEntry entry){
setValue(value);
setEntry(entry);
}
@Override
protected String format(){
return getValue().format();
}
@Override
public String toUserString(){
return getValue().toUserString();
}
/**
* @see BibTeXParser#checkCrossReferenceResolution(Key, BibTeXEntry)
*/
@Override
public boolean isResolved(){
return getEntry() != null;
}
public Value getValue(){
return this.value;
}
private void setValue(Value value){
this.value = value;
}
public BibTeXEntry getEntry(){
return this.entry;
}
private void setEntry(BibTeXEntry entry){
this.entry = entry;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/DigitStringValue.java 0000664 0000000 0000000 00000000425 14214333047 0024164 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class DigitStringValue extends LiteralValue {
DigitStringValue(){
}
public DigitStringValue(String string){
super(string);
}
@Override
protected String format(){
return getString();
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/Key.java 0000664 0000000 0000000 00000002003 14214333047 0021462 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.Serializable;
import java.util.Locale;
public class Key implements Serializable {
private String value = null;
transient
private String normalizedValue = null;
Key(){
}
public Key(String value){
setValue(value);
}
@Override
public String toString(){
return getValue();
}
@Override
public int hashCode(){
return (this.getNormalizedValue()).hashCode();
}
@Override
public boolean equals(Object object){
if(object instanceof Key){
Key that = (Key)object;
return (this.getNormalizedValue()).equals(that.getNormalizedValue());
}
return false;
}
public String getValue(){
return this.value;
}
private void setValue(String key){
if(key == null){
throw new IllegalArgumentException();
}
this.value = key;
}
private String getNormalizedValue(){
if(this.normalizedValue == null){
this.normalizedValue = getValue().toLowerCase(Locale.US);
}
return this.normalizedValue;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/KeyMap.java 0000664 0000000 0000000 00000001142 14214333047 0022123 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.util.LinkedHashMap;
public class KeyMap extends LinkedHashMap {
/**
* @return true If the {@link #keySet() key set} of the map was modified, false otherwise.
*
* @see #removeIfPresent(Key)
*/
boolean putIfMissing(Key key, V value){
if(containsKey(key)){
return false;
}
put(key, value);
return true;
}
/**
* @see #putIfMissing(Key, V)
*/
boolean removeIfPresent(Key key){
if(containsKey(key)){
remove(key);
return true;
}
return false;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/KeyValue.java 0000664 0000000 0000000 00000001043 14214333047 0022462 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class KeyValue extends Value {
private String string = null;
KeyValue(){
}
public KeyValue(String string){
setString(string);
}
public Key toKey(){
Key key = new Key(getString());
return key;
}
@Override
protected String format(){
return getString();
}
@Override
public String toUserString(){
return getString();
}
public String getString(){
return this.string;
}
private void setString(String string){
this.string = string;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LaTeXCommand.java 0000664 0000000 0000000 00000000522 14214333047 0023212 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class LaTeXCommand extends LaTeXObject {
private String name = null;
LaTeXCommand(){
}
public LaTeXCommand(String name){
setName(name);
}
public String getName(){
return this.name;
}
private void setName(String name){
this.name = name;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LaTeXGroup.java 0000664 0000000 0000000 00000000752 14214333047 0022735 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.util.Collections;
import java.util.List;
public class LaTeXGroup extends LaTeXObject {
private List objects = null;
LaTeXGroup(){
}
public LaTeXGroup(List objects){
setObjects(objects);
}
public List getObjects(){
return Collections.unmodifiableList(this.objects);
}
private void setObjects(List objects){
this.objects = objects;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LaTeXObject.java 0000664 0000000 0000000 00000000434 14214333047 0023044 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo (
use = JsonTypeInfo.Id.CLASS
)
abstract
public class LaTeXObject implements Serializable {
LaTeXObject(){
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LaTeXPrinter.java 0000664 0000000 0000000 00000020271 14214333047 0023262 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class LaTeXPrinter {
public LaTeXPrinter(){
}
public String print(List objects){
TextBuilder builder = new TextBuilder();
print(objects, builder);
return builder.buildString();
}
private void print(List objects, TextBuilder builder){
for(LaTeXObject object : objects){
if(object instanceof LaTeXCommand){
print((LaTeXCommand)object, builder);
} else
if(object instanceof LaTeXGroup){
print((LaTeXGroup)object, builder);
} else
if(object instanceof LaTeXString){
print((LaTeXString)object, builder);
} else
{
throw new IllegalArgumentException();
}
}
}
private void print(LaTeXCommand command, TextBuilder builder){
char accent = getAccent(command.getName());
if(accent > 0){
builder.setAccent(accent);
return;
}
String symbol = getSymbol(command.getName());
if(symbol != null){
builder.append(symbol);
}
}
private void print(LaTeXGroup group, TextBuilder builder){
builder.append(print(group.getObjects()));
}
private void print(LaTeXString string, TextBuilder builder){
String value = string.getValue();
if(value.contains("--")){
value = value.replace("---", "\u2014");
value = value.replace("--", "\u2013");
} // End if
if(value.contains("`")){
value = value.replace("``", "\u201c");
value = value.replace("`", "\u2018");
} // End if
if(value.contains("'")){
value = value.replace("''", "\u201d");
value = value.replace("'", "\u2019");
}
builder.append(value);
}
static
public String today(){
Calendar now = Calendar.getInstance();
return LATEX_TODAY.format(now.getTime());
}
private static final DateFormat LATEX_TODAY = new SimpleDateFormat("MMMM dd, yyyy");
static
private char getAccent(String name){
char c = (name.length() == 1 ? name.charAt(0) : 0);
switch(c){
case '`':
case '\'':
case '^':
case '\"':
case 'H':
case '~':
case 'c':
case 'k':
case '=':
case 'b':
case '.':
case 'd':
case 'r':
case 'u':
case 'v':
case 't':
return c;
default:
break;
}
return 0;
}
static
private char applyAccent(char accent, char c){
switch(accent){
// Grave
case '`':
switch(c){
case 'A':
return '\u00c0';
case 'E':
return '\u00c8';
case 'I':
return '\u00cc';
case 'O':
return '\u00d2';
case 'U':
return '\u00d9';
case 'a':
return '\u00e0';
case 'e':
return '\u00e8';
case 'i':
return '\u00ec';
case 'o':
return '\u00f2';
case 'u':
return '\u00f9';
default:
break;
}
break;
// Acute
case '\'':
switch(c){
case 'A':
return '\u00c1';
case 'E':
return '\u00c9';
case 'I':
return '\u00cd';
case 'O':
return '\u00d3';
case 'U':
return '\u00da';
case 'Y':
return '\u00dd';
case 'a':
return '\u00e1';
case 'e':
return '\u00e9';
case 'i':
return '\u00ed';
case 'o':
return '\u00f3';
case 'u':
return '\u00fa';
case 'y':
return '\u00fd';
default:
break;
}
break;
// Diaeresis
case '\"':
switch(c){
case 'A':
return '\u00c4';
case 'E':
return '\u00cb';
case 'I':
return '\u00cf';
case 'O':
return '\u00d6';
case 'U':
return '\u00dc';
case 'a':
return '\u00e4';
case 'e':
return '\u00eb';
case 'i':
return '\u00ef';
case 'o':
return '\u00f6';
case 'u':
return '\u00fc';
default:
break;
}
break;
// Tilde
case '~':
switch(c){
case 'A':
return '\u00c3';
case 'N':
return '\u00d1';
case 'O':
return '\u00d5';
case 'a':
return '\u00e3';
case 'n':
return '\u00f1';
case 'o':
return '\u00f5';
default:
break;
}
break;
// Ring above
case 'r':
switch(c){
case 'U':
return '\u016e';
case 'u':
return '\u016f';
default:
break;
}
break;
// Caron
case 'v':
switch(c){
case 'C':
return '\u010c';
case 'D':
return '\u010e';
case 'E':
return '\u011a';
case 'N':
return '\u0147';
case 'R':
return '\u0158';
case 'S':
return '\u0160';
case 'T':
return '\u0164';
case 'Z':
return '\u017d';
case 'c':
return '\u010d';
case 'd':
return '\u010f';
case 'e':
return '\u011b';
case 'n':
return '\u0148';
case 'r':
return '\u0159';
case 's':
return '\u0161';
case 't':
return '\u0165';
case 'z':
return '\u017e';
default:
break;
}
break;
default:
break;
}
return c;
}
static
public String getSymbol(String name){
return COMMAND_SYMBOLS.get(name);
}
static
public void setSymbol(String name, String symbol){
COMMAND_SYMBOLS.put(name, symbol);
}
private static final Map COMMAND_SYMBOLS = new LinkedHashMap<>();
static {
// Special symbols
setSymbol("#", "#");
setSymbol("$", "$");
setSymbol("%", "%");
setSymbol("&", "&");
setSymbol("\\", "\\");
setSymbol("^", "^");
setSymbol("_", "_");
setSymbol("{", "{");
setSymbol("}", "}");
setSymbol("~", "~");
// Non-ASCII letters
setSymbol("AA", "\u00c5");
setSymbol("AE", "\u00c6");
setSymbol("O", "\u00d8");
setSymbol("SS", "SS");
setSymbol("aa", "\u00e5");
setSymbol("ae", "\u00e6");
setSymbol("o", "\u00f8");
setSymbol("ss", "\u00df");
// Text-mode commands
setSymbol("textasciicircum", "^");
setSymbol("textasciitilde", "~");
setSymbol("textbackslash", "\\");
setSymbol("textbar", "|");
setSymbol("textbraceleft", "{");
setSymbol("textbraceright", "}");
setSymbol("textcopyrigh", "\u00a9");
setSymbol("textdollar", "$");
setSymbol("textellipsis", "\u2026");
setSymbol("textemdash", "\u2014");
setSymbol("textendash", "\u2013");
setSymbol("textgreater", ">");
setSymbol("textless", "<");
setSymbol("textquotedblleft", "\u201c");
setSymbol("textquotedblright", "\u201d");
setSymbol("textquoteleft", "\u2018");
setSymbol("textquoteright", "\u2019");
setSymbol("textregistered", "\u00ae");
setSymbol("texttrademark", "\u2122");
setSymbol("textunderscore", "_");
// Math- and text-mode commands
setSymbol("slash", "/");
setSymbol("backslash", "\\");
setSymbol("endash", "\u2013");
setSymbol("emdash", "\u2014");
setSymbol("ldots", "\u2026");
// Greek alphabet
setSymbol("alpha", "\u03b1");
setSymbol("beta", "\u03b2");
setSymbol("gamma", "\u03b3");
setSymbol("delta", "\u03b4");
setSymbol("epsilon", "\u03b5");
setSymbol("zeta", "\u03b6");
setSymbol("eta", "\u03b7");
setSymbol("theta", "\u03b8");
setSymbol("iota", "\u03b9");
setSymbol("kappa", "\u03ba");
setSymbol("lambda", "\u03bb");
setSymbol("mu", "\u03bc");
setSymbol("nu", "\u03bd");
setSymbol("xi", "\u03be");
setSymbol("omicron", "\u03bf"); // XXX
setSymbol("pi", "\u03c0");
setSymbol("rho", "\u03c1");
setSymbol("sigma", "\u03c2");
setSymbol("tau", "\u03c3");
setSymbol("upsilon", "\u03c4");
setSymbol("phi", "\u03c5");
setSymbol("chi", "\u03c6");
setSymbol("psi", "\u03c7");
setSymbol("omega", "\u03c8");
// Ready-made strings
setSymbol("today", today());
setSymbol("TeX", "TeX");
setSymbol("LaTeX", "LaTeX");
setSymbol("LaTeXe", "LaTeX\u03b5");
}
static
private class TextBuilder {
private StringBuilder sb = new StringBuilder();
private char accent = 0;
public void append(String string){
char accent = getAccent();
if(accent > 0){
if(string.length() > 0){
string = applyAccent(accent, string.charAt(0)) + string.substring(1);
}
setAccent((char)0);
}
this.sb.append(string);
}
public char getAccent(){
return this.accent;
}
private void setAccent(char accent){
this.accent = accent;
}
public String buildString(){
return this.sb.toString();
}
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LaTeXString.java 0000664 0000000 0000000 00000000531 14214333047 0023102 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class LaTeXString extends LaTeXObject {
private String value = null;
LaTeXString(){
}
public LaTeXString(String value){
setValue(value);
}
public String getValue(){
return this.value;
}
private void setValue(String value){
this.value = value;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/LiteralValue.java 0000664 0000000 0000000 00000000655 14214333047 0023336 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
abstract
public class LiteralValue extends Value {
private String string = null;
LiteralValue(){
}
public LiteralValue(String string){
setString(string);
}
@Override
public String toUserString(){
return getString();
}
public String getString(){
return this.string;
}
private void setString(String string){
this.string = string;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/ObjectResolutionException.java 0000664 0000000 0000000 00000000333 14214333047 0026107 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class ObjectResolutionException extends IllegalArgumentException {
public ObjectResolutionException(Key key){
super(key.getValue());
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/ReferenceValue.java 0000664 0000000 0000000 00000001755 14214333047 0023642 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class ReferenceValue extends Value implements Resolvable {
private KeyValue value = null;
private BibTeXString string = null;
ReferenceValue(){
}
public ReferenceValue(KeyValue value, BibTeXString string){
setValue(value);
setString(string);
}
@Override
protected String format(){
return getValue().format();
}
@Override
public String toUserString(){
BibTeXString string = getString();
if(string != null){
return (string.getValue()).toUserString();
}
return getValue().toUserString();
}
/**
* @see BibTeXParser#checkStringResolution(Key, BibTeXString)
*/
@Override
public boolean isResolved(){
return getString() != null;
}
public KeyValue getValue(){
return this.value;
}
private void setValue(KeyValue value){
this.value = value;
}
public BibTeXString getString(){
return this.string;
}
public void setString(BibTeXString string){
this.string = string;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/Resolvable.java 0000664 0000000 0000000 00000000300 14214333047 0023026 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import com.fasterxml.jackson.annotation.JsonIgnore;
public interface Resolvable {
@JsonIgnore
boolean isResolved();
} jbibtex-1.0.20/src/main/java/org/jbibtex/StringUtil.java 0000664 0000000 0000000 00000001266 14214333047 0023050 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class StringUtil {
private StringUtil(){
}
static
public String addIndent(String string, String indent){
return addIndent(string, 1, indent);
}
static
public String addIndent(String string, int level, String indent){
if(string.indexOf('\n') > -1){
String levelIndent = indent;
for(int i = 1; i < level; i++){
levelIndent += indent;
}
string = string.replaceAll("\\n", "\n" + levelIndent);
}
return string;
}
static
public String removeIndent(String string){
if(string.indexOf('\n') > -1){
string = string.replaceAll("\\n([\\ ,\\t])*", "\n");
}
return string;
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/StringValue.java 0000664 0000000 0000000 00000001673 14214333047 0023211 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
public class StringValue extends LiteralValue {
private Style style = null;
StringValue(){
}
public StringValue(String string, Style style){
super(string);
setStyle(style);
}
@Override
protected String format(){
Style style = getStyle();
return style.getBegin() + getString() + style.getEnd();
}
public Style getStyle(){
return this.style;
}
private void setStyle(Style style){
this.style = style;
}
static
public enum Style {
BRACED("{", "}"),
QUOTED("\"", "\""),
;
private String begin = null;
private String end = null;
Style(String begin, String end){
setBegin(begin);
setEnd(end);
}
public String getBegin(){
return this.begin;
}
private void setBegin(String begin){
this.begin = begin;
}
public String getEnd(){
return this.end;
}
private void setEnd(String end){
this.end = end;
}
}
} jbibtex-1.0.20/src/main/java/org/jbibtex/Value.java 0000664 0000000 0000000 00000001055 14214333047 0022014 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonTypeInfo (
use = JsonTypeInfo.Id.CLASS
)
abstract
public class Value implements Serializable {
Value(){
}
abstract
protected String format();
/**
* Returns a string representation of the object which is suitable for displaying to end users.
* The result may contain LaTeX language markup.
*
* @see LaTeXParser
* @see LaTeXPrinter
*/
abstract
public String toUserString();
} jbibtex-1.0.20/src/main/javacc/ 0000775 0000000 0000000 00000000000 14214333047 0016164 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/main/javacc/bibtex.jj 0000664 0000000 0000000 00000036234 14214333047 0017776 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
options {
JAVA_TEMPLATE_TYPE = "modern";
JDK_VERSION = "1.8";
KEEP_LINE_COLUMN = true;
STATIC = false;
}
PARSER_BEGIN(BibTeXParser)
package org.jbibtex;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class BibTeXParser {
private KeyMap macros = new KeyMap();
private BibTeXDatabase database = null;
private List exceptions = new ArrayList();
private long id = 1L;
public BibTeXParser() throws ParseException, TokenMgrException {
this("");
// Default macros
addMacro("jan", "January");
addMacro("feb", "February");
addMacro("mar", "March");
addMacro("apr", "April");
addMacro("may", "May");
addMacro("jun", "June");
addMacro("jul", "July");
addMacro("aug", "August");
addMacro("sep", "September");
addMacro("oct", "October");
addMacro("nov", "November");
addMacro("dec", "December");
}
/**
* Parses the BibTeX document in "normal" mode.
* The parser throws an exception is an error condition is detected.
*
* @throws ObjectResolutionException If the database is inconsistent.
*
* @throws TokenMgrException If a token cannot be produced.
* @throws ParseException If the produced sequence of tokens cannot be consumed.
*
* @see CharacterFilterReader
*/
public BibTeXDatabase parse(Reader reader) throws ObjectResolutionException, ParseException, TokenMgrException {
ReInit(new StreamProvider(reader));
token_source.SwitchTo(IN_HEADER);
return Database(false);
}
/**
* Parses the BibTeX document in "error recovery" mode.
* The parser does its best to recover from typical error conditions by skipping the problematic object definition.
* The parser maintains a {@link #getExceptions() list of exceptions}. This list is cleared when a parse method is invoked again.
*
* @throws ObjectResolutionException If the database is inconsistent.
*
* @see CharacterFilterReader
*/
public BibTeXDatabase parseFully(Reader reader) throws ObjectResolutionException {
ReInit(new StreamProvider(reader));
token_source.SwitchTo(IN_HEADER);
try {
return Database(true);
} catch(TokenMgrException tme){
throw new RuntimeException(tme);
} catch(ParseException pe){
throw new RuntimeException(pe);
}
}
/**
* Checks the string argument before constructing a new {@link ReferenceValue} instance.
* The default behaviour is to prohibit unresolved references.
*
* @throws ObjectResolutionException If the string is null.
*
* @see BibTeXDatabase#resolveString(Key)
* @see BibTeXParser#getMacros()
*/
public void checkStringResolution(Key key, BibTeXString string){
if(string == null){
throw new ObjectResolutionException(key);
}
}
private void resolveCrossReferences(){
Map entries = getDatabase().getEntries();
for(BibTeXEntry entry : entries.values()){
Map fields = entry.getFields();
Value value = fields.get(BibTeXEntry.KEY_CROSSREF);
if((value == null) || (value instanceof CrossReferenceValue)){
continue;
}
Key key = new Key(value.toUserString());
BibTeXEntry object = getDatabase().resolveEntry(key);
checkCrossReferenceResolution(key, object);
entry.addField(BibTeXEntry.KEY_CROSSREF, new CrossReferenceValue(value, object));
}
}
/**
* Checks the entry argument before constructing a new {@link CrossReferenceValue} instance.
* The default behaviour is to prohibit unresolved references.
*
* @throws ObjectResolutionException If the entry is null.
*
* @see BibTeXDatabase#resolveEntry(Key)
*/
public void checkCrossReferenceResolution(Key key, BibTeXEntry entry){
if(entry == null){
throw new ObjectResolutionException(key);
}
}
/**
* Generates a key value for an anonymous BibTeX bibliography database entry.
*
* @see BibTeXEntry#getKey
* @see BibTeXDatabase#resolveEntry(Key)
*/
public String nextKey(){
return String.valueOf("jbibtex-" + this.id++);
}
public BibTeXDatabase getDatabase(){
return this.database;
}
private void setDatabase(BibTeXDatabase database){
this.database = database;
}
public List getExceptions(){
return Collections.unmodifiableList(this.exceptions);
}
public KeyMap getMacros(){
return this.macros;
}
public void addMacro(String key, String value){
addMacro(new BibTeXString(new Key(key), new StringValue(value, StringValue.Style.BRACED)));
}
public void addMacro(BibTeXString macro){
this.macros.put(macro.getKey(), macro);
}
public void removeMacro(String key){
this.macros.remove(new Key(key));
}
public void removeMacro(BibTeXString macro){
this.macros.remove(macro.getKey());
}
private void handleException(E e, boolean performErrorRecovery) throws E {
if(!performErrorRecovery){
throw e;
}
this.exceptions.add(e);
}
static
private boolean isDigitString(String string){
for(int i = 0; i < string.length(); i++){
char c = string.charAt(i);
// Only ASCII digits from '0' to '9'
if(c < '0' || c > '9'){
return false;
}
}
return (string.length() > 0);
}
static
private BibTeXDatabase parseBibTeXDatabase(File file) throws ParseException {
try {
Reader reader = new FileReader(file);
try {
BibTeXParser parser = new BibTeXParser();
return parser.parse(reader);
} finally {
reader.close();
}
} catch(Exception e){
throw new ParseException(e.getMessage());
}
}
static
private class Field {
private Key key = null;
private Value value = null;
private Field(Key key, Value value){
setKey(key);
setValue(value);
}
public Key getKey(){
return this.key;
}
private void setKey(Key key){
this.key = key;
}
public Value getValue(){
return this.value;
}
private void setValue(Value value){
this.value = value;
}
}
}
PARSER_END(BibTeXParser)
TOKEN_MGR_DECLS : {
void backup(int n){
input_stream.backup(n);
}
}
SKIP :
{
< ( ~["%", "@"] )* > : DEFAULT
}
MORE :
{
"%" : IN_INLINE_COMMENT
}
SPECIAL_TOKEN :
{
< INLINE_COMMENT : ( ~["\r", "\n"] )* ("\r" | "\n" | "\r\n")? > : DEFAULT
}
MORE :
{
< ~[] >
}
TOKEN :
{
< TEXT : ~[] >
}
SKIP :
{
"\t"
|
"\n"
|
"\f"
|
"\r"
|
" "
}
TOKEN :
{
< AT : "@" >
|
< COMMA : "," >
|
< EQUALS : "=" >
|
< HASH : "#" >
|
< LBRACE : "{">
|
< LPAREN : "(" >
|
< QUOTE : "\"" >
|
< RBRACE : "}" >
|
< RPAREN : ")" >
}
TOKEN :
{
< COMMENT : ( ["c", "C"] ["o", "O"] ["m", "M"] ["m", "M"] ["e", "E"] ["n", "N"] ["t", "T"] ) >
|
< INCLUDE : ( ["i", "I"] ["n", "N"] ["c", "C"] ["l", "L"] ["u", "U"] ["d", "D"] ["e", "E"] ) >
|
< PREAMBLE : ( ["p", "P"] ["r", "R"] ["e", "E"] ["a", "A"] ["m", "M"] ["b", "B"] ["l", "L"] ["e", "E"] ) >
|
< STRING : ( ["s", "S"] ["t", "T"] ["r", "R"] ["i", "I"] ["n", "N"] ["g", "G"] ) >
}
TOKEN :
{
// NAME is a subtype (restriction) of IDENTIFIER, therefore it must be declared first
< NAME : ( | ) ( | )* >
|
< IDENTIFIER: ( | ) ( | )* >
|
< #LETTER_OR_DIGIT: ( | | | ) >
|
< #ASCII_LETTER : ["a"-"z", "A"-"Z"] >
|
< #ASCII_DIGIT : ["0"-"9"] >
|
< #LATIN_LETTER : ["\u00c0"-"\u00d6", "\u00d8"-"\u00f6", "\u00f8"-"\u00ff"] >
|
< #UNICODE_LETTER : ["\u0100"-"\u1fff", "\u20ac", "\u2122"] >
|
< #NAME_START_SYMBOL: [".", "_"] >
|
< #NAME_CONTINUATION_SYMBOL: ["+", "-", ".", ":", "_"] >
|
< #IDENTIFIER_START_SYMBOL : ["(", "-", ".", "[", "_"] >
|
< #IDENTIFIER_CONTINUATION_SYMBOL : ["!", "#", "$", "%", "&", "'", "(", ")", "*", "+", "-", ".", "/", ":", ";", "<", ">", "?", "[", "\\", "]", "^", "_", "|", "~" ] >
}
private BibTeXDatabase Database(boolean performErrorRecovery) :
{
BibTeXDatabase database = new BibTeXDatabase();
BibTeXObject object = null;
}
{
{
setDatabase(database);
this.exceptions.clear();
}
(
try {
|
object = Object() { database.addObject(object); }
} catch(TokenMgrException tme){
handleException(tme, performErrorRecovery);
SkipTo("@");
} catch(ParseException pe){
handleException(pe, performErrorRecovery);
SkipTo("@");
}
)*
{
resolveCrossReferences();
setDatabase(null);
return database;
}
}
private BibTeXObject Object() :
{
BibTeXObject object;
}
{
(
LOOKAHEAD( )
object = Comment()
|
LOOKAHEAD( )
object = Include()
|
LOOKAHEAD( )
object = Preamble()
|
LOOKAHEAD( )
object = String()
|
object = Entry()
)
{
return object;
}
}
private BibTeXComment Comment() :
{
String string;
}
{
(
string = Literal(1, "}")
)
{
return new BibTeXComment(new StringValue(string, StringValue.Style.BRACED));
}
}
private BibTeXInclude Include():
{
String string;
}
{
(
string = Literal(1, "}")
)
{
BibTeXDatabase database = parseBibTeXDatabase(new File(string));
return new BibTeXInclude(new StringValue(string, StringValue.Style.BRACED), database);
}
}
private BibTeXPreamble Preamble() :
{
Value value;
}
{
(
value = Value()
|
value = Value()
)
{
return new BibTeXPreamble(value);
}
}
private BibTeXString String() :
{
Field field;
}
{
(
field = Assignment()
|
field = Assignment()
)
{
return new BibTeXString(field.getKey(), field.getValue());
}
}
private BibTeXEntry Entry() :
{
Token type;
Token key = null;
List fields;
}
{
type =
(
(
LOOKAHEAD( Identifier() )
key = Identifier() { fields = Collections.emptyList(); }
|
LOOKAHEAD( Identifier() )
key = Identifier() fields = AssignmentList() ( )?
|
( )? fields = AssignmentList() ( )?
)
|
(
LOOKAHEAD( Identifier() )
key = Identifier() { fields = Collections.emptyList(); }
|
LOOKAHEAD( Identifier() )
key = Identifier() fields = AssignmentList() ( )?
|
( )? fields = AssignmentList() ( )?
)
)
{
BibTeXEntry entry = new BibTeXEntry(new Key(type.image), key != null ? new Key(key.image) : new Key(nextKey()));
for(Field field : fields){
entry.addField(field.getKey(), field.getValue());
}
return entry;
}
}
private Field Assignment() :
{
Key key;
Value value;
}
{
key = Key() value = Value()
{
return new Field(key, value);
}
}
private List AssignmentList() :
{
List fields = new ArrayList();
Field field;
}
{
field = Assignment() { fields.add(field); } ( LOOKAHEAD( Name() ) field = Assignment() { fields.add(field); } )*
{
return fields;
}
}
private Token Name() :
{
Token token;
}
{
(
token =
|
token =
|
token =
|
token =
|
token =
)
{
return token;
}
}
private Token Identifier() :
{
Token token;
}
{
(
token =
|
token =
|
token =
|
token =
|
token =
|
token =
)
{
return token;
}
}
private Key Key() :
{
Token token;
}
{
token = Name()
{
return new Key(token.image);
}
}
private Value Value() :
{
Value left;
Value right = null;
}
{
left = SimpleValue() ( right = Value() )?
{
if(right != null){
return new ConcateValue(left, right);
}
return left;
}
}
private Value SimpleValue() :
{
String string;
Token token;
Value result;
}
{
(
string = Literal(1, "}")
{
result = new StringValue(string, StringValue.Style.BRACED);
}
|
string = Literal(0, "\"")
{
result = new StringValue(string, StringValue.Style.QUOTED);
}
|
token = Identifier()
{
boolean digits = isDigitString(token.image);
if(!digits){
KeyValue value = new KeyValue(token.image);
Key key = value.toKey();
BibTeXString object = getDatabase().resolveString(key);
if(object == null){
KeyMap macros = getMacros();
object = macros.get(key);
}
checkStringResolution(key, object);
result = new ReferenceValue(value, object);
} else
{
result = new DigitStringValue(token.image);
}
}
)
{
return result;
}
}
JAVACODE
private void SkipTo(String symbol) throws ParseException {
if(symbol == null){
throw new IllegalArgumentException();
}
SetState(IN_LITERAL);
for(Token prevToken = null, token = getNextToken(); true; prevToken = token, token = getNextToken()){
if(token.kind == BibTeXParserConstants.EOF){
throw new ParseException("Reached unexpected EOF token");
} // End if
if(symbol.equals(token.image)){
break;
}
}
token_source.backup(symbol.length());
SetState(DEFAULT);
}
JAVACODE
private String Literal(int braceLevel, String delimiter) throws ParseException {
StringBuilder sb = new StringBuilder(64);
if(braceLevel < 0){
throw new IllegalArgumentException();
}
SetState(IN_LITERAL);
for(Token prevToken = null, token = getNextToken(); true; prevToken = token, token = getNextToken()){
if(token.kind == BibTeXParserConstants.EOF){
throw new ParseException("Reached unexpected EOF token");
}
boolean escaped = (prevToken != null && "\\".equals(prevToken.image));
if(!escaped){
if("{".equals(token.image)){
braceLevel++;
} else
if("}".equals(token.image)){
braceLevel--;
}
} // End if
if(delimiter.equals(token.image) && braceLevel == 0){
break;
}
sb.append(token.image);
}
SetState(DEFAULT);
return StringUtil.removeIndent(sb.toString());
}
/**
* JavaCC hack for doing lexical state transitions syntactically
*
* http://www.engr.mun.ca/~theo/JavaCC-FAQ/SetState.txt
*/
JAVACODE
private void SetState(int state) {
if (state != token_source.curLexState) {
Token root = new Token(), last=root;
root.next = null;
// First, we build a list of tokens to push back, in backwards order
while (token.next != null) {
Token t = token;
// Find the token whose token.next is the last in the chain
while (t.next != null && t.next.next != null)
t = t.next;
// put it at the end of the new chain
last.next = t.next;
last = t.next;
// If there are special tokens, these go before the regular tokens,
// so we want to push them back onto the input stream in the order
// we find them along the specialToken chain.
if (t.next.specialToken != null) {
Token tt=t.next.specialToken;
while (tt != null) {
last.next = tt;
last = tt;
tt.next = null;
tt = tt.specialToken;
}
}
t.next = null;
};
while (root.next != null) {
token_source.backup(root.next.image.length());
root.next = root.next.next;
}
jj_ntk = -1;
token_source.SwitchTo(state);
}
}
jbibtex-1.0.20/src/main/javacc/latex.jj 0000664 0000000 0000000 00000007053 14214333047 0017633 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
options {
GENERATE_BOILERPLATE = false;
JAVA_TEMPLATE_TYPE = "modern";
JDK_VERSION = "1.8";
KEEP_LINE_COLUMN = true;
STATIC = false;
}
PARSER_BEGIN(LaTeXParser)
package org.jbibtex;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
public class LaTeXParser {
public LaTeXParser() throws ParseException {
this("");
}
/**
* @see LaTeXParser#parse(Reader)
*/
public List parse(String string) throws ParseException, TokenMgrException {
return parse(new StringReader(string));
}
/**
* @throws TokenMgrException If the input contains invalid characters
*
* @see CharacterFilterReader
*/
public List parse(Reader reader) throws ParseException, TokenMgrException {
ReInit(new StreamProvider(reader));
return LaTeX();
}
}
PARSER_END(LaTeXParser)
TOKEN :
{
< BACKSLASH : "\\" >
|
< LBRACE : "{" >
|
< RBRACE : "}" >
}
TOKEN :
{
< WHITESPACE : ["\t", "\n", " "] >
|
< SPECIAL : ["#", "$", "%", "&", "^", "_", "~"] >
|
< NON_SPECIAL : ["!"-"\"", "\'"-"/", ":"-"@", "[", "]", "`", "|", "\u007f", "\u2013", "\u2014", "\u2018", "\u2019", "\u201c", "\u201d", "\u2212"] >
}
TOKEN :
{
< ASCII_LETTER : ["a"-"z", "A"-"Z"] >
|
< ASCII_DIGIT : ["0"-"9"] >
|
< LATIN_SUPPLEMENT : ["\u00a0"-"\u00ff"] >
|
< UNICODE_LETTER : ["\u0100"-"\u1fff", "\u20ac", "\u2122"] >
}
private List LaTeX() :
{
List objects;
}
{
objects = ObjectList()
{
return objects;
}
}
private List ObjectList() :
{
List objects = new ArrayList();
LaTeXObject object;
}
{
( object = Object() { objects.add(object); } )*
{
return objects;
}
}
private LaTeXObject Object() :
{
LaTeXObject object;
}
{
(
object = Command()
|
object = Group()
|
object = String()
)
{
return object;
}
}
private LaTeXCommand Command() :
{
String name;
}
{
(
name = Name() Whitespace()
|
name = SpecialCharacter()
|
name = NonSpecialCharacter()
)
{
return new LaTeXCommand(name);
}
}
private String Name() :
{
StringBuilder sb = new StringBuilder(16);
Token token;
}
{
token = { sb.append(token.image); } ( LOOKAHEAD( ) token = { sb.append(token.image); } )*
{
return sb.toString();
}
}
private void Whitespace() :
{}
{
( LOOKAHEAD( WhitespaceCharacter() ) WhitespaceCharacter() )*
}
private String WhitespaceCharacter() :
{
Token token;
}
{
token =
{
return token.image;
}
}
private String SpecialCharacter() :
{
Token token;
}
{
(
token =
|
token =
|
token =
|
token =
)
{
return token.image;
}
}
private String NonSpecialCharacter() :
{
Token token;
}
{
token =
{
return token.image;
}
}
private LaTeXGroup Group() :
{
List objects;
}
{
objects = ObjectList()
{
return new LaTeXGroup(objects);
}
}
private LaTeXString String() :
{
StringBuilder sb = new StringBuilder(64);
String string;
}
{
string = TextCharacter() { sb.append(string); } ( LOOKAHEAD( TextCharacter() ) string = TextCharacter() { sb.append(string); } )*
{
return new LaTeXString(sb.toString());
}
}
private String TextCharacter() :
{
Token token;
}
{
(
token =
|
token =
|
token =
|
token =
|
token =
|
token =
)
{
return token.image;
}
} jbibtex-1.0.20/src/test/ 0000775 0000000 0000000 00000000000 14214333047 0014770 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/test/java/ 0000775 0000000 0000000 00000000000 14214333047 0015711 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/test/java/org/ 0000775 0000000 0000000 00000000000 14214333047 0016500 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/test/java/org/jbibtex/ 0000775 0000000 0000000 00000000000 14214333047 0020127 5 ustar 00root root 0000000 0000000 jbibtex-1.0.20/src/test/java/org/jbibtex/BibTeXParserTest.java 0000664 0000000 0000000 00000014062 14214333047 0024127 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2012 University of Tartu
*/
package org.jbibtex;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
public class BibTeXParserTest {
@Test
public void parseBibtex() throws Exception {
BibTeXParser parser = new BibTeXParser();
BibTeXDatabase database = parseFully(parser, "/bibtex.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
Map entries = database.getEntries();
assertNotNull(entries.get(new Key("first")));
assertNotNull(entries.get(new Key("last")));
List exceptions = parser.getExceptions();
assertEquals(1, exceptions.size());
}
@Test
public void parseJava() throws Exception {
BibTeXParser parser = new BibTeXParser();
parser.addMacro("ack-bnb", "Barbara N. Beeton");
parser.addMacro("ack-bs", "Bruce Schneier");
parser.addMacro("ack-kl", "Ken Lunde");
BibTeXDatabase database = parse(parser, "/java.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
List objects = database.getObjects();
assertEquals(4498, objects.size());
Map strings = database.getStrings();
assertEquals(467, strings.size());
Map entries = database.getEntries();
assertEquals(4030, entries.size());
Collection values = entries.values();
assertEquals(1890, countType(values, BibTeXEntry.TYPE_ARTICLE));
assertEquals(1675, countType(values, BibTeXEntry.TYPE_BOOK));
assertEquals(232, countType(values, BibTeXEntry.TYPE_INPROCEEDINGS));
assertEquals(8, countType(values, BibTeXEntry.TYPE_MANUAL));
assertEquals(13, countType(values, BibTeXEntry.TYPE_MASTERSTHESIS));
assertEquals(62, countType(values, BibTeXEntry.TYPE_MISC));
assertEquals(6, countType(values, new Key("periodical")));
assertEquals(1, countType(values, BibTeXEntry.TYPE_PHDTHESIS));
assertEquals(114, countType(values, BibTeXEntry.TYPE_PROCEEDINGS));
assertEquals(20, countType(values, BibTeXEntry.TYPE_TECHREPORT));
assertEquals(9, countType(values, BibTeXEntry.TYPE_UNPUBLISHED));
}
@Test
public void parseMendeley() throws Exception {
BibTeXParser parser = new BibTeXParser();
BibTeXDatabase database = parse(parser, "/mendeley.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
}
@Test
public void parseUnix() throws Exception {
BibTeXParser parser = new BibTeXParser();
parser.addMacro("ack-hk", "Hanna K{\\\"o}lodziejska");
parser.addMacro("ack-kl", "Ken Lunde");
parser.addMacro("ack-kr", "Karin Remington");
parser.addMacro("ack-pb", "Preston Briggs");
parser.addMacro("ack-rfb", "Ronald F. Boisvert");
BibTeXDatabase database = parse(parser, "/unix.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
List objects = database.getObjects();
assertEquals(2632, objects.size());
Map strings = database.getStrings();
assertEquals(358, strings.size());
Map entries = database.getEntries();
assertEquals(2273, entries.size());
Collection values = entries.values();
assertEquals(645, countType(values, BibTeXEntry.TYPE_ARTICLE));
assertEquals(1447, countType(values, BibTeXEntry.TYPE_BOOK));
assertEquals(6, countType(values, BibTeXEntry.TYPE_INCOLLECTION));
assertEquals(48, countType(values, BibTeXEntry.TYPE_INPROCEEDINGS));
assertEquals(31, countType(values, BibTeXEntry.TYPE_MANUAL));
assertEquals(12, countType(values, BibTeXEntry.TYPE_MASTERSTHESIS));
assertEquals(7, countType(values, BibTeXEntry.TYPE_MISC));
assertEquals(6, countType(values, new Key("periodical")));
assertEquals(2, countType(values, BibTeXEntry.TYPE_PHDTHESIS));
assertEquals(34, countType(values, BibTeXEntry.TYPE_PROCEEDINGS));
assertEquals(33, countType(values, BibTeXEntry.TYPE_TECHREPORT));
assertEquals(2, countType(values, BibTeXEntry.TYPE_UNPUBLISHED));
}
@Test
public void parseWiley() throws Exception {
BibTeXParser parser = new BibTeXParser();
BibTeXDatabase database = parse(parser, "/wiley.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
}
@Test
public void parseZotero() throws Exception {
BibTeXParser parser = new BibTeXParser();
BibTeXDatabase database = parse(parser, "/zotero.bib");
ensureSerializability(database);
ensureJsonSerializability(database);
}
static
private void ensureSerializability(BibTeXDatabase database){
BibTeXDatabase clonedDatabase;
try {
clonedDatabase = SerializationUtil.clone(database);
} catch(Exception e){
throw new AssertionError();
}
assertEquals((database.getObjects()).size(), (clonedDatabase.getObjects()).size());
}
static
private void ensureJsonSerializability(BibTeXDatabase database){
BibTeXDatabase clonedDatabase;
try {
clonedDatabase = SerializationUtil.jsonClone(database);
} catch(Exception e){
throw new AssertionError();
}
assertEquals((database.getObjects()).size(), (clonedDatabase.getObjects()).size());
}
static
private BibTeXDatabase parse(BibTeXParser parser, String path) throws Exception {
InputStream is = (BibTeXParserTest.class).getResourceAsStream(path);
try {
Reader reader = new InputStreamReader(is, "US-ASCII");
try {
return parser.parse(reader);
} finally {
reader.close();
}
} finally {
is.close();
}
}
static
private BibTeXDatabase parseFully(BibTeXParser parser, String path) throws Exception {
InputStream is = (BibTeXParserTest.class).getResourceAsStream(path);
try {
Reader reader = new InputStreamReader(is, "US-ASCII");
try {
return parser.parseFully(reader);
} finally {
reader.close();
}
} finally {
is.close();
}
}
static
private int countType(Collection entries, Key type){
int count = 0;
for(BibTeXEntry entry : entries){
if((entry.getType()).equals(type)){
count++;
}
}
return count;
}
} jbibtex-1.0.20/src/test/java/org/jbibtex/CharacterFilterReaderTest.java 0000664 0000000 0000000 00000001727 14214333047 0026026 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2014 University of Tartu
*/
package org.jbibtex;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CharacterFilterReaderTest {
@Test
public void readCharacter() throws IOException {
Reader reader = new CharacterFilterReader(new CharArrayReader(buffer));
assertEquals('a', reader.read());
assertEquals('1', reader.read());
// EOF
assertEquals(-1, reader.read());
reader.close();
}
@Test
public void readCharacterArray() throws IOException {
Reader reader = new CharacterFilterReader(new CharArrayReader(buffer));
char[] result = new char[512];
int count = reader.read(result);
assertEquals(2, count);
assertEquals('a', result[0]);
assertEquals('1', result[1]);
// EOF
assertEquals(-1, reader.read());
reader.close();
}
private static final char[] buffer = {(char)0, 'a', (char)0, '1', (char)0};
} jbibtex-1.0.20/src/test/java/org/jbibtex/KeyMapTest.java 0000664 0000000 0000000 00000000773 14214333047 0023027 0 ustar 00root root 0000000 0000000 /*
* Copyright (c) 2014 University of Tartu
*/
package org.jbibtex;
import org.junit.Test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class KeyMapTest {
@Test
public void putAndRemove(){
KeyMap