2 Copyright (C) 2006 Raik Nagel <kiar@users.sourceforge.net>
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13 * Neither the name of the author nor the names of its contributors may be
14 used to endorse or promote products derived from this software without
15 specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 // created by : r.nagel 19.04.2006
32 // function : Handling of bibtex fields.
33 // All bibtex-field related stuff should be placed here!
34 // Because we can export these informations into additional
35 // config files -> simple extension and definition of new fields....
37 // todo : - handling of identically fields with different names
38 // e.g. LCCN = lib-congress
39 // - group id for each fields, e.g. standard, jurabib, bio....
40 // - add a additional properties functionality into the
41 // BibtexSingleField class
43 // modified : r.nagel 25.04.2006
44 // export/import of some definition from/to a xml file
46 package net.sf.jabref ;
49 import net.sf.jabref.util.*;
50 import org.w3c.dom.Element;
51 import org.w3c.dom.NodeList;
53 public class BibtexFields
55 public static final String KEY_FIELD = "bibtexkey" ;
57 // some internal fields
58 public static final String
60 GROUPSEARCH = "__groupsearch",
61 MARKED = "__markedentry",
63 TIMESTAMP = "timestamp", // it's also definied at the JabRefPreferences class
64 ENTRYTYPE = "entrytype",
66 // Using this when I have no database open or when I read
67 // non bibtex file formats (used by the ImportFormatReader.java)
68 DEFAULT_BIBTEXENTRY_ID = "__ID" ;
70 public static final String[] DEFAULT_INSPECTION_FIELDS = new String[]
71 {"author", "title", "year", KEY_FIELD};
75 private static final BibtexFields runtime = new BibtexFields() ;
77 // contains all bibtex-field objects (BibtexSingleField)
78 private HashMap fieldSet = null ;
80 // contains all known (and public) bibtex fieldnames
81 private Object[] PUBLIC_FIELDS = null ;
83 private BibtexFields()
85 fieldSet = new HashMap() ;
86 BibtexSingleField dummy = null ;
88 // FIRST: all standard fields
89 // These are the fields that BibTex might want to treat, so these
90 // must conform to BibTex rules.
91 add( new BibtexSingleField( "address", true, GUIGlobals.SMALL_W ) ) ;
92 // An annotation. It is not used by the standard bibliography styles,
93 // but may be used by others that produce an annotated bibliography.
94 // http://www.ecst.csuchico.edu/~jacobsd/bib/formats/bibtex.html
95 add( new BibtexSingleField( "annote", true, GUIGlobals.LARGE_W ) ) ;
96 add( new BibtexSingleField( "author", true, GUIGlobals.MEDIUM_W, 280 ) ) ;
97 add( new BibtexSingleField( "booktitle", true, 175 ) ) ;
98 add( new BibtexSingleField( "chapter", true, GUIGlobals.SMALL_W ) ) ;
99 add( new BibtexSingleField( "crossref", true, GUIGlobals.SMALL_W ) ) ;
100 add( new BibtexSingleField( "edition", true, GUIGlobals.SMALL_W ) ) ;
101 add( new BibtexSingleField( "editor", true, GUIGlobals.MEDIUM_W, 280 ) ) ;
102 add( new BibtexSingleField( "howpublished", true, GUIGlobals.MEDIUM_W ) ) ;
103 add( new BibtexSingleField( "institution", true, GUIGlobals.MEDIUM_W ) ) ;
105 dummy = new BibtexSingleField( "journal", true, GUIGlobals.SMALL_W ) ;
106 dummy.setExtras("journalNames");
108 add( new BibtexSingleField( "key", true ) ) ;
109 add( new BibtexSingleField( "month", true, GUIGlobals.SMALL_W ) ) ;
110 add( new BibtexSingleField( "note", true, GUIGlobals.MEDIUM_W ) ) ;
111 add( new BibtexSingleField( "number", true, GUIGlobals.SMALL_W, 60 ) ) ;
112 add( new BibtexSingleField( "organization", true, GUIGlobals.MEDIUM_W ) ) ;
113 add( new BibtexSingleField( "pages", true, GUIGlobals.SMALL_W ) ) ;
114 add( new BibtexSingleField( "publisher", true, GUIGlobals.MEDIUM_W ) ) ;
115 add( new BibtexSingleField( "school", true, GUIGlobals.MEDIUM_W ) ) ;
116 add( new BibtexSingleField( "series", true, GUIGlobals.SMALL_W ) ) ;
117 add( new BibtexSingleField( "title", true, 400 ) ) ;
118 add( new BibtexSingleField( "type", true, GUIGlobals.SMALL_W ) ) ;
119 add( new BibtexSingleField( "volume", true, GUIGlobals.SMALL_W, 60 ) ) ;
120 add( new BibtexSingleField( "year", true, GUIGlobals.SMALL_W, 60 ) ) ;
122 // some semi-standard fields
123 dummy = new BibtexSingleField( KEY_FIELD, true ) ;
127 dummy = new BibtexSingleField( "doi", true, GUIGlobals.SMALL_W ) ;
128 dummy.setExtras("external");
130 add( new BibtexSingleField( "eid", true, GUIGlobals.SMALL_W ) ) ;
132 dummy = new BibtexSingleField( "date", true ) ;
137 // additional fields ------------------------------------------------------
138 dummy = new BibtexSingleField( "citeseercitationcount", false,
139 GUIGlobals.SMALL_W, 75) ;
140 dummy.setAlternativeDisplayName("Popularity") ;
142 add( new BibtexSingleField( "location", false ) ) ;
143 add( new BibtexSingleField( "abstract", false, GUIGlobals.LARGE_W, 400 ) ) ;
145 dummy = new BibtexSingleField( "url", false, GUIGlobals.SMALL_W) ;
146 dummy.setExtras("external");
149 dummy = new BibtexSingleField( "citeseerurl", false, GUIGlobals.SMALL_W ) ;
150 dummy.setExtras("external");
153 dummy = new BibtexSingleField( "pdf", false, GUIGlobals.SMALL_W ) ;
154 dummy.setExtras("browseDoc");
157 dummy = new BibtexSingleField( "ps", false, GUIGlobals.SMALL_W ) ;
158 dummy.setExtras("browseDocZip");
160 add( new BibtexSingleField( "comment", false, GUIGlobals.MEDIUM_W ) ) ;
161 add( new BibtexSingleField( "keywords", false, GUIGlobals.SMALL_W ) ) ;
162 //FIELD_EXTRAS.put("keywords", "selector");
164 add( new BibtexSingleField( "search", false, 75 ) ) ;
167 // some internal fields ----------------------------------------------
168 dummy = new BibtexSingleField( GUIGlobals.NUMBER_COL, false, 32 ) ;
170 dummy.setWriteable(false);
171 dummy.setDisplayable(false);
174 dummy = new BibtexSingleField( OWNER, false, GUIGlobals.SMALL_W ) ;
178 dummy = new BibtexSingleField( TIMESTAMP, false, GUIGlobals.SMALL_W ) ;
179 dummy.setExtras("datepicker");
183 dummy = new BibtexSingleField( ENTRYTYPE, false, 75 ) ;
187 dummy = new BibtexSingleField( SEARCH, false) ;
189 dummy.setWriteable(false);
190 dummy.setDisplayable(false);
193 dummy = new BibtexSingleField( GROUPSEARCH, false) ;
195 dummy.setWriteable(false);
196 dummy.setDisplayable(false);
199 dummy = new BibtexSingleField( MARKED, false) ;
201 dummy.setWriteable(true); // This field must be written to file!
202 dummy.setDisplayable(false);
205 // read external field definitions
206 readXML( Globals.additionalFields ) ;
208 // collect all public fields for the PUBLIC_FIELDS array
209 Vector pFields = new Vector( fieldSet.size()) ;
210 for(Iterator iter = fieldSet.values().iterator(); iter.hasNext() ; )
212 BibtexSingleField sField = (BibtexSingleField) iter.next() ;
213 if (sField.isPublic() )
215 pFields.add( sField.getFieldName() );
216 // or export the complet BibtexSingleField ?
217 // BibtexSingleField.toString() { return fieldname ; }
221 PUBLIC_FIELDS = pFields.toArray() ;
223 java.util.Arrays.sort( PUBLIC_FIELDS );
227 /** insert a field into the internal list */
228 private void add( BibtexSingleField field )
230 // field == null check
231 String key = field.name ;
232 fieldSet.put( key, field ) ;
235 /** read a xml definiton file and put only NEW fields into the field list */
236 private void readXML( String resName )
238 TXMLReader reader = new TXMLReader(resName) ;
239 if (reader.isReady() )
241 // get a list of all fields
242 NodeList fieldNodes = reader.getNodes("field") ;
244 int tagsCount = fieldNodes.getLength() ;
245 for (int t = 0 ; t < tagsCount ; t++)
247 Element entry = (Element) fieldNodes.item(t) ;
248 String fName = reader.readStringAttribute(entry, "name", null) ;
249 if (fName != null) // something found ?
251 fName = fName.toLowerCase() ;
252 BibtexSingleField dummy = (BibtexSingleField) fieldSet.get( fName ) ;
253 if (dummy == null) // unknown field
255 dummy = new BibtexSingleField(reader, entry) ;
256 fieldSet.put(fName, dummy) ;
263 // --------------------------------------------------------------------------
265 // --------------------------------------------------------------------------
266 private static final BibtexSingleField getField( String name )
270 return (BibtexSingleField) runtime.fieldSet.get(name.toLowerCase()) ;
276 public static String getFieldExtras( String name )
278 BibtexSingleField sField = getField( name ) ;
281 return sField.getExtras() ;
286 public static double getFieldWeight( String name )
288 BibtexSingleField sField = getField( name ) ;
291 return sField.getWeight() ;
293 return GUIGlobals.DEFAULT_FIELD_WEIGHT ;
296 public static void setFieldWeight( String fieldName, double weight )
298 BibtexSingleField sField = getField( fieldName ) ;
301 sField.setWeight( weight ) ;
305 public static int getFieldLength( String name )
307 BibtexSingleField sField = getField( name ) ;
310 return sField.getLength() ;
312 return GUIGlobals.DEFAULT_FIELD_LENGTH ;
315 // returns an alternative name for the given fieldname
316 public static String getFieldDisplayName( String fieldName )
318 BibtexSingleField sField = getField( fieldName ) ;
321 return sField.getAlternativeDisplayName() ;
326 public static boolean isWriteableField( String field )
328 BibtexSingleField sField = getField( field ) ;
331 return sField.isWriteable() ;
336 public static boolean isDisplayableField( String field )
338 BibtexSingleField sField = getField( field ) ;
341 return sField.isDisplayable() ;
347 * Returns true if the given field is a standard Bibtex field.
349 * @param field a <code>String</code> value
350 * @return a <code>boolean</code> value
352 public static boolean isStandardField( String field )
354 BibtexSingleField sField = getField( field ) ;
357 return sField.isStandard() ;
362 /** returns an string-array with all fieldnames */
363 public static Object[] getAllFieldNames()
365 return runtime.PUBLIC_FIELDS ;
368 /** returns the fieldname of the entry at index t */
369 public static String getFieldName( int t )
371 return (String) runtime.PUBLIC_FIELDS[t] ;
374 /** returns the number of available fields */
375 public static int numberOfPublicFields()
377 return runtime.PUBLIC_FIELDS.length ;
381 public static int getPreferredFieldLength(String name) {
382 int l = DEFAULT_FIELD_LENGTH;
383 Object o = fieldLength.get(name.toLowerCase());
385 l = ((Integer)o).intValue();
390 // --------------------------------------------------------------------------
391 // a container class for all properties of a bibtex-field
392 // --------------------------------------------------------------------------
393 private class BibtexSingleField
395 private static final int
396 STANDARD = 0x01, // it is a standard bibtex-field
397 PRIVATE = 0x02, // internal use, e.g. owner, timestamp
398 DISPLAYABLE = 0x04, // These fields cannot be shown inside the source editor panel
399 WRITEABLE = 0x08 ; // These fields will not be saved to the .bib file.
402 private String name ;
404 // contains the standard, privat, displayable, writable infos
405 // default is: not standard, public, displayable and writable
406 private int flag = DISPLAYABLE | WRITEABLE ;
408 private int length = GUIGlobals.DEFAULT_FIELD_LENGTH ;
409 private double weight = GUIGlobals.DEFAULT_FIELD_WEIGHT ;
411 // a alternative displayname, e.g. used for
412 // "citeseercitationcount"="Popularity"
413 private String alternativeDisplayName = null ;
416 // fieldExtras contains mappings to tell the EntryEditor to add a specific
417 // function to this field, for instance a "browse" button for the "pdf" field.
418 private String extras = null ;
420 // a comma separated list of alternative bibtex-fieldnames, e.g.
421 // "LCCN" is the same like "lib-congress"
422 // private String otherNames = null ;
424 // a Hashmap for a lot of additional "not standard" properties
425 // todo: add the handling in a key=value manner
426 // private HashMap props = new HashMap() ;
428 // some constructors ;-)
429 public BibtexSingleField( String fieldName )
434 public BibtexSingleField( String fieldName, boolean pStandard )
437 setFlag( pStandard, STANDARD) ;
440 public BibtexSingleField( String fieldName, boolean pStandard, double pWeight)
443 setFlag( pStandard, STANDARD) ;
447 public BibtexSingleField( String fieldName, boolean pStandard, int pLength)
450 setFlag( pStandard, STANDARD) ;
454 public BibtexSingleField( String fieldName, boolean pStandard,
455 double pWeight, int pLength)
458 setFlag( pStandard, STANDARD) ;
463 /** the constructor reads all neccessary data from the xml file */
464 public BibtexSingleField( TXMLReader reader, Element node)
466 // default is: not standard, public, displayable and writable
467 flag = DISPLAYABLE | WRITEABLE ;
469 name = reader.readStringAttribute(node, "name", "field") ;
470 name = name.toLowerCase() ;
473 String wStr = reader.readStringAttribute(node, "weight", null) ;
476 int hCode = wStr.toLowerCase().hashCode() ;
477 if (hCode == "small".hashCode())
479 weight = GUIGlobals.SMALL_W ;
481 else if (hCode == "medium".hashCode())
483 weight = GUIGlobals.MEDIUM_W ;
485 else if (hCode == "large".hashCode())
487 weight = GUIGlobals.LARGE_W ;
489 else // try to convert to a double value
493 weight = Double.parseDouble(wStr) ;
494 if ((weight < 0.0) || (weight > GUIGlobals.MAX_FIELD_WEIGHT))
496 weight = GUIGlobals.DEFAULT_FIELD_WEIGHT ;
501 weight = GUIGlobals.DEFAULT_FIELD_WEIGHT ;
505 length = reader.readIntegerAttribute( node, "length", GUIGlobals.DEFAULT_FIELD_LENGTH ) ;
507 extras = reader.readStringAttribute(node, "extras", null) ;
510 // -----------------------------------------------------------------------
511 // -----------------------------------------------------------------------
513 private void setFlag( boolean onOff, int flagID)
515 if (onOff) // set the flag
517 flag = flag | flagID ;
519 else // unset the flag,
521 flag = flag & ( 0xff ^ flagID ) ;
525 private boolean isSet( int flagID )
527 if ( (flag & flagID) == flagID)
533 // -----------------------------------------------------------------------
534 public boolean isStandard()
536 return isSet( STANDARD ) ;
539 public void setPrivate()
541 flag = flag | PRIVATE ;
544 public boolean isPrivate()
546 return isSet( PRIVATE ) ;
549 public void setPublic()
551 setFlag( false, PRIVATE ) ;
554 public boolean isPublic()
556 return !isSet( PRIVATE ) ;
559 public void setDisplayable(boolean value)
561 setFlag( value, DISPLAYABLE ) ;
564 public boolean isDisplayable()
566 return isSet(DISPLAYABLE) ;
570 public void setWriteable(boolean value)
572 setFlag( value, WRITEABLE ) ;
575 public boolean isWriteable()
577 return isSet( WRITEABLE ) ;
580 // -----------------------------------------------------------------------
581 public void setAlternativeDisplayName( String aName)
583 alternativeDisplayName = aName ;
586 public String getAlternativeDisplayName()
588 return alternativeDisplayName ;
590 // -----------------------------------------------------------------------
592 public void setExtras( String pExtras)
597 // fieldExtras contains mappings to tell the EntryEditor to add a specific
598 // function to this field, for instance a "browse" button for the "pdf" field.
599 public String getExtras()
603 // -----------------------------------------------------------------------
605 public void setWeight( double value )
607 this.weight = value ;
610 public double getWeight()
615 // -----------------------------------------------------------------------
616 public int getLength()
621 // -----------------------------------------------------------------------
623 public String getFieldName()