package org.jabref.model.entry;
import java.util.Locale;
import java.util.Objects;
/**
* This class models a BibTex String ("@String")
*/
public class BibtexString implements Cloneable {
/**
* Type of a \@String.
* <p>
* Differentiate a \@String based on its usage:
* <p>
* - {@link #AUTHOR}: prefix "a", for author and editor fields.
* - {@link #INSTITUTION}: prefix "i", for institution and organization
* field
* - {@link #PUBLISHER}: prefix "p", for publisher fields
* - {@link #OTHER}: no prefix, for any field
* <p>
* Examples:
* <p>
* \@String { aKahle = "Kahle, Brewster " } -> author
* \@String { aStallman = "Stallman, Richard" } -> author
* \@String { iMIT = "{Massachusetts Institute of Technology ({MIT})}" } -> institution
* \@String { pMIT = "{Massachusetts Institute of Technology ({MIT}) press}" } -> publisher
* \@String { anct = "Anecdote" } -> other
* \@String { eg = "for example" } -> other
* \@String { et = " and " } -> other
* \@String { lBigMac = "Big Mac" } -> other
* <p>
* Usage:
* <p>
* \@Misc {
* title = "The GNU Project"
* author = aStallman # et # aKahle
* institution = iMIT
* publisher = pMIT
* note = "Just " # eg
* }
*/
public enum Type {
AUTHOR("a"),
INSTITUTION("i"),
PUBLISHER("p"),
OTHER("");
private final String prefix;
Type(String prefix) {
this.prefix = prefix;
}
public static Type get(String key) {
if (key.length() <= 1) {
return OTHER;
}
// Second character is not upper case
// aStallman -> AUTHOR
// asdf -> OTHER
if (!(String.valueOf(key.charAt(1))).toUpperCase(Locale.ROOT).equals(String.valueOf(key.charAt(1)))) {
return OTHER;
}
for (Type t : Type.values()) {
if (t.prefix.equals(String.valueOf(key.charAt(0)))) {
return t;
}
}
return OTHER;
}
}
private String name;
private String content;
private String id;
private Type type;
private String parsedSerialization;
private boolean hasChanged;
public BibtexString(String name, String content) {
this.id = IdGenerator.next();
this.name = name;
this.content = content;
hasChanged = true;
type = Type.get(name);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
hasChanged = true;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
hasChanged = true;
type = Type.get(name);
}
/*
* Never returns null
*/
public String getContent() {
return content == null ? "" : content;
}
public void setContent(String content) {
this.content = content;
hasChanged = true;
}
public Type getType() {
return type;
}
public void setParsedSerialization(String parsedSerialization) {
this.parsedSerialization = parsedSerialization;
hasChanged = false;
}
public String getParsedSerialization() {
return parsedSerialization;
}
public boolean hasChanged() {
return hasChanged;
}
/*
* Returns user comments (arbitrary text before the string) if there are any. If not returns the empty string
*/
public String getUserComments() {
if (parsedSerialization != null) {
try {
// get the text before the string
String prolog = parsedSerialization.substring(0, parsedSerialization.indexOf('@'));
// delete trailing whitespaces (between string and text)
prolog = prolog.replaceFirst("\\s+$", "");
// if there is any non whitespace text, write it with proper line separation
if (prolog.length() > 0) {
return prolog;
}
} catch (StringIndexOutOfBoundsException ignore) {
// if this occurs a broken parsed serialization has been set, so just do nothing
}
}
return "";
}
@Override
public Object clone() {
BibtexString clone = new BibtexString(name, content);
clone.setId(id);
return clone;
}
@Override
public String toString() {
return name + "=" + content;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BibtexString that = (BibtexString) o;
return hasChanged == that.hasChanged &&
Objects.equals(name, that.name) &&
Objects.equals(content, that.content) &&
Objects.equals(id, that.id) &&
type == that.type &&
Objects.equals(parsedSerialization, that.parsedSerialization);
}
@Override
public int hashCode() {
return Objects.hash(name, content, id, type, parsedSerialization, hasChanged);
}
}