2 Copyright (C) 2003 Morten O. Alver, Nizar N. Batada
4 All programs in this directory and
5 subdirectories are published under the GNU General Public License as
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 Further information about the GNU GPL is available at:
24 http://www.gnu.org/copyleft/gpl.ja.html
27 package net.sf.jabref;
32 import net.sf.jabref.groups.*;
34 public class MetaData {
35 private HashMap metaData = new HashMap();
36 private StringReader data;
37 private GroupTreeNode groupsRoot = null;
38 private File file = null; // The File where this base gets saved.
41 * The MetaData object stores all meta data sets in Vectors. To ensure that
42 * the data is written correctly to string, the user of a meta data Vector
43 * must simply make sure the appropriate changes are reflected in the Vector
46 public MetaData(HashMap inData, BibtexDatabase db) {
47 boolean groupsTreePresent = false;
48 Vector flatGroupsData = null;
49 Vector treeGroupsData = null;
50 // The first version (0) lacked a version specification,
51 // thus this value defaults to 0.
52 int groupsVersionOnDisk = 0;
54 if (inData != null) for (Iterator i = inData.keySet().iterator(); i.hasNext();) {
55 String key = (String) i.next();
56 data = new StringReader((String) inData.get(key));
58 Vector orderedData = new Vector();
59 // We must allow for ; and \ in escape sequences.
61 while ((unit = getNextUnit(data)) != null) {
62 orderedData.add(unit);
64 } catch (IOException ex) {
65 System.err.println("Weird error while parsing meta data.");
67 if (key.equals("groupsversion")) {
68 if (orderedData.size() >= 1)
69 groupsVersionOnDisk = Integer.parseInt(orderedData.firstElement().toString());
70 } else if (key.equals("groupstree")) {
71 groupsTreePresent = true;
72 treeGroupsData = orderedData; // save for later user
73 // actual import operation is handled later because "groupsversion"
74 // tag might not yet have been read
75 } else if (key.equals("groups")) {
76 flatGroupsData = orderedData;
78 putData(key, orderedData);
82 // this possibly handles import of a previous groups version
83 if (groupsTreePresent)
84 putGroups(treeGroupsData, db, groupsVersionOnDisk);
86 if (!groupsTreePresent && flatGroupsData != null) {
87 groupsRoot = VersionHandling.importFlatGroups(flatGroupsData);
92 * The MetaData object can be constructed with no data in it.
99 * Add default metadata for new database:
101 public void initializeNewDatabase() {
102 metaData.put(Globals.SELECTOR_META_PREFIX + "keywords", new Vector());
103 metaData.put(Globals.SELECTOR_META_PREFIX + "author", new Vector());
104 metaData.put(Globals.SELECTOR_META_PREFIX + "journal", new Vector());
105 metaData.put(Globals.SELECTOR_META_PREFIX + "publisher", new Vector());
108 public Iterator iterator() {
109 return metaData.keySet().iterator();
112 public Vector getData(String key) {
113 return (Vector) metaData.get(key);
116 public void remove(String key) {
117 metaData.remove(key);
121 * Stores the specified data in this object, using the specified key. For
122 * certain keys (e.g. "groupstree"), the objects in orderedData are
123 * reconstructed from their textual (String) representation if they are of
124 * type String, and stored as an actual instance.
126 public void putData(String key, Vector orderedData) {
127 metaData.put(key, orderedData);
131 * Look up the directory set up for the given field type for this database.
132 * If no directory is set up, return that defined in global preferences.
133 * @param fieldName The field type
134 * @return The default directory for this field type.
136 public String getFileDirectory(String fieldName) {
137 // There can be up to two directory definitions for these files - the database's
138 // metadata can specify a directory, or the preferences can specify one. The
139 // metadata directory takes precedence if defined.
140 String key = fieldName + "Directory";
142 Vector vec = getData(key);
143 if ((vec != null) && (vec.size() > 0)) {
144 dir = (String)vec.get(0);
145 // If this directory is relative, we try to interpret it as relative to
146 // the file path of this bib file:
147 if (!(new File(dir)).isAbsolute() && (file != null)) {
148 String relDir = new StringBuffer(file.getParent()).
149 append(System.getProperty("file.separator")).
150 append(dir).toString();
151 // If this directory actually exists, it is very likely that the
152 // user wants us to use it:
153 if ((new File(relDir)).exists())
158 dir = Globals.prefs.get(key);
161 //System.out.println("MetaData: dir: '"+dir+"' relative: "+(new File(dir)).isAbsolute());
165 private void putGroups(Vector orderedData, BibtexDatabase db, int version) {
167 groupsRoot = VersionHandling.importGroups(orderedData, db,
169 } catch (Exception e) {
170 // we cannot really do anything about this here
171 System.err.println(e);
175 public GroupTreeNode getGroups() {
180 * Sets a new group root node. <b>WARNING </b>: This invalidates everything
181 * returned by getGroups() so far!!!
183 public void setGroups(GroupTreeNode root) {
188 * Writes all data to the specified writer, using each object's toString()
191 public void writeMetaData(Writer out) throws IOException {
192 // write all meta data except groups
193 for (Iterator i = metaData.keySet().iterator(); i.hasNext();) {
194 String key = (String) i.next();
195 StringBuffer sb = new StringBuffer();
196 Vector orderedData = (Vector) metaData.get(key);
197 if (orderedData.size() >= 0) {
198 sb.append("@comment{").append(GUIGlobals.META_FLAG).append(key).append(":");
199 for (int j = 0; j < orderedData.size(); j++) {
200 sb.append(Util.quote((String) orderedData.elementAt(j), ";", '\\')).append(";");
203 sb.append(Globals.NEWLINE);
204 sb.append(Globals.NEWLINE);
206 wrapStringBuffer(sb, Globals.METADATA_LINE_LENGTH);
207 out.write(sb.toString());
209 // write groups if present. skip this if only the root node exists
210 // (which is always the AllEntriesGroup).
211 if (groupsRoot != null && groupsRoot.getChildCount() > 0) {
212 StringBuffer sb = new StringBuffer();
213 // write version first
214 sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupsversion:");
215 sb.append(""+VersionHandling.CURRENT_VERSION+";");
217 sb.append(Globals.NEWLINE);
218 sb.append(Globals.NEWLINE);
219 out.write(sb.toString());
221 // now write actual groups
222 sb = new StringBuffer();
223 sb.append("@comment{").append(GUIGlobals.META_FLAG).append("groupstree:");
224 sb.append(Globals.NEWLINE);
225 // GroupsTreeNode.toString() uses "\n" for separation
226 StringTokenizer tok = new StringTokenizer(groupsRoot.getTreeAsString(),Globals.NEWLINE);
227 while (tok.hasMoreTokens()) {
229 new StringBuffer(Util.quote(tok.nextToken(), ";", '\\') + ";");
230 wrapStringBuffer(s, Globals.METADATA_LINE_LENGTH);
232 sb.append(Globals.NEWLINE);
235 sb.append(Globals.NEWLINE);
236 sb.append(Globals.NEWLINE);
237 out.write(sb.toString());
241 private void wrapStringBuffer(StringBuffer sb, int lineLength) {
242 for (int i=lineLength; i<sb.length(); i+=lineLength+1) {
243 sb.insert(i, Globals.NEWLINE);
248 * Reads the next unit. Units are delimited by ';'.
250 private String getNextUnit(Reader reader) throws IOException {
252 boolean escape = false;
253 StringBuffer res = new StringBuffer();
254 while ((c = reader.read()) != -1) {
258 } else if (c == '\\') {
260 } else if (c == ';') {
266 if (res.length() > 0)
267 return res.toString();
271 public File getFile() {
275 public void setFile(File file) {