fb5ede4fe1e4f72461fd82021143ac469437a9d6
[debian/jabref.git] / src / java / net / sf / jabref / export / layout / LayoutEntry.java
1 /*
2 Copyright (C) 2003 Morten O. Alver
3 All programs in this directory and
4 subdirectories are published under the GNU General Public License as
5 described below.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or (at
10 your option) any later version.
11
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA
21
22 Further information about the GNU GPL is available at:
23 http://www.gnu.org/copyleft/gpl.ja.html
24
25 */
26 package net.sf.jabref.export.layout;
27
28 import wsi.ra.tool.WSITools;
29
30 import wsi.ra.types.StringInt;
31
32 import java.util.Vector;
33
34 import net.sf.jabref.BibtexDatabase;
35 import net.sf.jabref.BibtexEntry;
36 import net.sf.jabref.Globals;
37
38
39 /**
40  * DOCUMENT ME!
41  *
42  * @author $author$
43  * @version $Revision: 1.9 $
44  */
45 public class LayoutEntry
46 {
47     //~ Instance fields ////////////////////////////////////////////////////////
48
49     private LayoutFormatter[] option;
50     private String text;
51     private LayoutEntry[] layoutEntries;
52     private int type;
53     private String classPrefix;
54
55     //~ Constructors ///////////////////////////////////////////////////////////
56
57     public LayoutEntry(StringInt si, String classPrefix_) throws Exception
58     {
59         type = si.i;
60         classPrefix = classPrefix_;
61
62         if (si.i == LayoutHelper.IS_LAYOUT_TEXT)
63         {
64             text = si.s;
65         }
66         else if (si.i == LayoutHelper.IS_SIMPLE_FIELD)
67         {
68             text = si.s.trim();
69         }
70         else if (si.i == LayoutHelper.IS_FIELD_START)
71         {
72         }
73         else if (si.i == LayoutHelper.IS_FIELD_END)
74         {
75         }
76         else if (si.i == LayoutHelper.IS_OPTION_FIELD)
77         {
78             Vector v = new Vector();
79             WSITools.tokenize(v, si.s, "\n");
80
81             if (v.size() == 1)
82             {
83                 text = (String) v.get(0);
84             }
85             else
86             {
87                 text = ((String) v.get(0)).trim();
88
89                 //try
90                 //{
91                     option = getOptionalLayout((String) v.get(1));
92                 //}
93                 // catch (Exception e)
94                 //{
95                 //    e.printStackTrace();
96                 //}
97             }
98         }
99
100         //              else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
101         //              {
102         //              }
103     }
104    
105     public LayoutEntry(Vector parsedEntries, String classPrefix_, int layoutType) throws Exception
106     {
107       classPrefix = classPrefix_;
108         String blockStart = null;
109         String blockEnd = null;
110         StringInt si;
111         Vector blockEntries = null;
112         Vector tmpEntries = new Vector();
113         LayoutEntry le;
114         si = (StringInt) parsedEntries.get(0);
115         blockStart = si.s;
116         si = (StringInt) parsedEntries.get(parsedEntries.size() - 1);
117         blockEnd = si.s;
118
119         if (!blockStart.equals(blockEnd))
120         {
121             System.err.println("Field start and end entry must be equal.");
122         }
123
124         type = layoutType;
125         text = si.s;
126
127         for (int i = 1; i < (parsedEntries.size() - 1); i++)
128         {
129             si = (StringInt) parsedEntries.get(i);
130
131             //System.out.println("PARSED-ENTRY: "+si.s+"="+si.i);
132             if (si.i == LayoutHelper.IS_LAYOUT_TEXT)
133             {
134             }
135             else if (si.i == LayoutHelper.IS_SIMPLE_FIELD)
136             {
137             }
138             else if ((si.i == LayoutHelper.IS_FIELD_START) ||
139                         (si.i == LayoutHelper.IS_GROUP_START))
140             {
141                 blockEntries = new Vector();
142                 blockStart = si.s;
143             }
144             else if ((si.i == LayoutHelper.IS_FIELD_END) ||
145                         (si.i == LayoutHelper.IS_GROUP_END))
146             {
147                 if (blockStart.equals(si.s))
148                 {
149                     blockEntries.add(si);
150                     if (si.i == LayoutHelper.IS_GROUP_END)
151                         le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_GROUP_START);
152                     else
153                         le = new LayoutEntry(blockEntries, classPrefix, LayoutHelper.IS_FIELD_START);                        
154                     tmpEntries.add(le);
155                     blockEntries = null;
156                 }
157                 else
158                 {
159                     System.out.println(
160                         "Nested field entries are not implemented !!!");
161                 }
162             }
163             else if (si.i == LayoutHelper.IS_OPTION_FIELD)
164             {
165             }
166
167             //                  else if (si.i == LayoutHelper.IS_OPTION_FIELD_PARAM)
168             //                  {
169             //                  }
170             if (blockEntries == null)
171             {
172                 //System.out.println("BLOCK ADD: "+si.s+"="+si.i);
173                 tmpEntries.add(new LayoutEntry(si, classPrefix));
174             }
175             else
176             {
177                 blockEntries.add(si);
178             }
179         }
180
181         layoutEntries = new LayoutEntry[tmpEntries.size()];
182
183         for (int i = 0; i < tmpEntries.size(); i++)
184         {
185             layoutEntries[i] = (LayoutEntry) tmpEntries.get(i);
186
187             //System.out.println(layoutEntries[i].text);
188         }
189     }
190     
191     //~ Methods ////////////////////////////////////////////////////////////////
192
193     public String doLayout(BibtexEntry bibtex, BibtexDatabase database)
194     {
195         if (type == LayoutHelper.IS_LAYOUT_TEXT)
196         {
197             return text;
198         }
199         else if (type == LayoutHelper.IS_SIMPLE_FIELD)
200         {
201             if (text.equals("bibtextype"))
202             {
203                 return bibtex.getType().getName();
204             }
205
206             String field = getField(bibtex, text, database);
207
208             if (field == null)
209             {
210                 return null;
211             }
212             else
213             {
214                 
215                 return field;
216
217             }
218         }
219         else if ((type == LayoutHelper.IS_FIELD_START) ||
220                         (type == LayoutHelper.IS_GROUP_START))
221         {
222             String field = getField(bibtex, text, database);
223             //String field = (String) bibtex.getField(text);
224
225             if ((field == null) || ((type == LayoutHelper.IS_GROUP_START) &&
226                                                         (field.equalsIgnoreCase(LayoutHelper.getCurrentGroup()))))
227             {
228                 return null;
229             }
230             else
231             {
232                 if (type == LayoutHelper.IS_GROUP_START) {
233                     LayoutHelper.setCurrentGroup(field);
234                 }
235                 StringBuffer sb = new StringBuffer(100);
236                 String fieldText;
237                 boolean previousSkipped = false;
238
239                 for (int i = 0; i < layoutEntries.length; i++)
240                 {
241                     fieldText = layoutEntries[i].doLayout(bibtex, database);
242
243                     //System.out.println("'" + fieldText + "'");
244                     if (fieldText == null)
245                     {
246                         if ((i + 1) < layoutEntries.length)
247                         {
248                             if (layoutEntries[i + 1].doLayout(bibtex, database).trim()
249                                                         .length() == 0)
250                             {
251                                 //System.out.println("MISSING: "+bibtex);
252                                 i++;
253                                 previousSkipped = true;
254
255                                 continue;
256                             }
257                         }
258                     }
259                     else
260                     {
261                         // if previous was skipped --> remove leading line breaks
262                         if (previousSkipped)
263                         {
264                             int eol = 0;
265
266                             while ((eol < fieldText.length()) &&
267                                     ((fieldText.charAt(eol) == '\n') ||
268                                     (fieldText.charAt(eol) == '\r')))
269                             {
270                                 eol++;
271                             }
272
273                             if (eol < fieldText.length())
274                             {
275                                 sb.append(fieldText.substring(eol));
276                             }
277                         }
278                         else
279                         {
280                             //System.out.println("ENTRY-BLOCK: " + layoutEntries[i].doLayout(bibtex));
281                             sb.append(fieldText);
282                         }
283                     }
284
285                     previousSkipped = false;
286                 }
287
288                 return sb.toString();
289             }
290         }
291         else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END))
292         {
293         }
294         else if (type == LayoutHelper.IS_OPTION_FIELD)
295         {
296             //System.out.println("doLayout IS_OPTION_FIELD '"+text+"'");
297             String fieldEntry;
298
299             if (text.equals("bibtextype"))
300             {
301                 fieldEntry = bibtex.getType().getName();
302             }
303             else{
304             // changed section begin - arudert
305             // resolve field (recognized by leading backslash) or text
306             String field = text.startsWith("\\") ? getField(bibtex, text.substring(1), database) : getText(text, database);
307             // changed section end - arudert
308             
309             //String field = (String) bibtex.getField(text);
310
311             if (field == null)
312             {
313                 fieldEntry = "";
314             }
315             else
316             {
317                 fieldEntry = field;
318             }
319             }
320
321             //System.out.println("OPTION: "+option);
322             if (option != null)
323             {
324               for (int i=0; i<option.length; i++) {
325                 fieldEntry = option[i].format(fieldEntry);
326               }
327             }
328
329             return fieldEntry;
330         }
331
332         //              else if (type == LayoutHelper.IS_OPTION_FIELD_PARAM)
333         //              {
334         //              }
335         return "";
336     }
337
338   // added section - begin (arudert)
339   /**
340    * Do layout for general formatters (no bibtex-entry fields).
341    * 
342    * @param database Bibtex Database
343    * @return 
344    */
345   public String doLayout(BibtexDatabase database)
346   {
347       if (type == LayoutHelper.IS_LAYOUT_TEXT)
348       {
349           return text;
350       }
351       else if (type == LayoutHelper.IS_SIMPLE_FIELD)
352       {
353           throw new UnsupportedOperationException("bibtext entry fields not allowed in begin or end layout");
354       }
355       else if ((type == LayoutHelper.IS_FIELD_START) ||
356                 (type == LayoutHelper.IS_GROUP_START))
357       {
358         throw new UnsupportedOperationException("field and group starts not allowed in begin or end layout");
359       }
360       else if ((type == LayoutHelper.IS_FIELD_END) || (type == LayoutHelper.IS_GROUP_END))
361       {
362         throw new UnsupportedOperationException("field and group ends not allowed in begin or end layout");
363       }
364       else if (type == LayoutHelper.IS_OPTION_FIELD)
365       {
366           String field = getText(text, database);
367           if (option != null)
368           {
369             for (int i=0; i<option.length; i++) {
370               field = option[i].format(field);
371             }
372           }
373
374           return field;
375       }
376       return "";
377   }
378   // added section - end (arudert)
379
380     /**
381      * @param string
382      * @return
383      */
384     private LayoutFormatter[] getOptionalLayout(String formatterName)
385         throws Exception
386     {
387       String[] formatters = formatterName.split(",");
388       //System.out.println(":"+formatterName);
389         LayoutFormatter[] formatter = new LayoutFormatter[formatters.length];
390         for (int i=0; i<formatter.length; i++) {
391           //System.out.println(":::"+formatters[i]);
392           try
393           {
394             try {
395               formatter[i] = (LayoutFormatter) Class.forName(classPrefix + formatters[i])
396                   .newInstance();
397             } catch (Throwable ex2) {
398               formatter[i] = (LayoutFormatter) Class.forName(formatters[i])
399                   .newInstance();
400             }
401           }
402           catch (ClassNotFoundException ex)
403           {
404             throw new Exception(Globals.lang("Formatter not found")+": "+formatters[i]);
405           }
406           catch (InstantiationException ex)
407           {
408             throw new Exception(formatterName + " can not be instantiated.");
409           }
410           catch (IllegalAccessException ex)
411           {
412             throw new Exception(formatterName + " can't be accessed.");
413           }
414
415           if (formatter == null)
416           {
417             throw new Exception(Globals.lang("Formatter not found")+": "+formatters[i]);
418           }
419         }
420
421         return formatter;
422     }
423
424
425     // changed section begin - arudert
426     /**
427      * Returns a text with references resolved according to an optionally given database. 
428      */
429     private String getText(String text, BibtexDatabase database) {
430       String res = text;
431       // changed section end - arudert
432       if ((res != null) && (database != null))
433         res = database.resolveForStrings(res);
434       return res;
435     }
436     // changed section end - arudert
437     
438     private String getField(BibtexEntry bibtex, String field, BibtexDatabase database) {
439
440       String res = (String)bibtex.getField(field);
441         
442         if ((res != null) && (database != null))
443         res = database.resolveForStrings(res);
444
445         return res;
446     }
447 }
448 ///////////////////////////////////////////////////////////////////////////////
449 //  END OF FILE.
450 ///////////////////////////////////////////////////////////////////////////////