p2izing the editor
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / propertysheet / reference / ReferencePropertySource.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.taxeditor.propertysheet.reference;
11
12 import java.beans.PropertyChangeEvent;
13 import java.beans.PropertyChangeListener;
14 import java.beans.PropertyChangeSupport;
15 import java.lang.reflect.Constructor;
16 import java.lang.reflect.InvocationTargetException;
17 import java.lang.reflect.Method;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Set;
23 import java.util.Vector;
24
25 import org.apache.log4j.Logger;
26 import org.eclipse.ui.views.properties.ComboBoxPropertyDescriptor;
27 import org.eclipse.ui.views.properties.IPropertyDescriptor;
28 import org.eclipse.ui.views.properties.IPropertySource;
29 import org.eclipse.ui.views.properties.PropertyDescriptor;
30 import org.eclipse.ui.views.properties.TextPropertyDescriptor;
31
32 import eu.etaxonomy.cdm.common.CdmUtils;
33 import eu.etaxonomy.cdm.model.agent.Team;
34 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
35 import eu.etaxonomy.cdm.model.common.TimePeriod;
36 import eu.etaxonomy.cdm.model.reference.Article;
37 import eu.etaxonomy.cdm.model.reference.BibtexReference;
38 import eu.etaxonomy.cdm.model.reference.Book;
39 import eu.etaxonomy.cdm.model.reference.BookSection;
40 import eu.etaxonomy.cdm.model.reference.CdDvd;
41 import eu.etaxonomy.cdm.model.reference.Database;
42 import eu.etaxonomy.cdm.model.reference.Generic;
43 import eu.etaxonomy.cdm.model.reference.InProceedings;
44 import eu.etaxonomy.cdm.model.reference.Journal;
45 import eu.etaxonomy.cdm.model.reference.Map;
46 import eu.etaxonomy.cdm.model.reference.Patent;
47 import eu.etaxonomy.cdm.model.reference.PersonalCommunication;
48 import eu.etaxonomy.cdm.model.reference.PrintSeries;
49 import eu.etaxonomy.cdm.model.reference.PrintedUnitBase;
50 import eu.etaxonomy.cdm.model.reference.Proceedings;
51 import eu.etaxonomy.cdm.model.reference.PublicationBase;
52 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
53 import eu.etaxonomy.cdm.model.reference.Report;
54 import eu.etaxonomy.cdm.model.reference.SectionBase;
55 import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
56 import eu.etaxonomy.cdm.model.reference.Thesis;
57 import eu.etaxonomy.cdm.model.reference.WebPage;
58 import eu.etaxonomy.taxeditor.ITaxEditorConstants;
59 import eu.etaxonomy.taxeditor.editor.reference.IReferenceSearch;
60 import eu.etaxonomy.taxeditor.model.CdmUtil;
61 import eu.etaxonomy.taxeditor.propertysheet.TimePeriodPropertySource;
62 import eu.etaxonomy.taxeditor.propertysheet.YearValidator;
63
64 /**
65 * Supplies the properties of a <code>ReferenceBase</code> object for display by
66 * a <code>PropertySheet</code>.
67 * <p>
68 * Includes a drop-down menu that allows the user to change <code>ReferenceBase</code>
69 * subclasses. This causes all fields except <code>TitleCache</code> to be wiped clean.
70 * <p>
71 * Normally, this would be called from another <code>IPropertySource</code>
72 * as follows:
73 * <pre>
74 * public Object getPropertyValue(Object id) {
75 *
76 * ...
77 *
78 * if (id.equals(P_ID_BIBREF)) {
79 * ReferenceBase citation = descriptionElement.getCitation();
80 * ReferencePropertySource bibRefPropertySource = new ReferencePropertySource(citation);
81 * bibRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
82 * @Override
83 * public void propertyChange(PropertyChangeEvent evt) {
84 * descriptionElement.setCitation((ReferenceBase) evt.getNewValue());
85 * }
86 * });
87 * return bibRefPropertySource;
88 * }
89 * </pre>
90 * <p>
91 * Note: if <code>P_ID_BIBREF</code> in the above example is associated with an editable
92 * <code>TextPropertyDescriptor</code>, it will initalize its cell editor by calling
93 * <code>getEditableValue()</code>. If associated with a non-editable <code>PropertyDescriptor</code>,
94 * it will get its value from <code>getString()</code>.
95 * @author p.ciardelli
96 * @created 03.11.2008
97 * @version 1.0
98 */
99 public class ReferencePropertySource implements IPropertySource {
100 private static final Logger logger = Logger
101 .getLogger(ReferencePropertySource.class);
102
103 ReferenceBase reference;
104
105 // Property unique keys
106 public static final String P_ID_SEARCH = "P_ID_SEARCH";
107 public static final String P_ID_EDITABLECACHE = "P_ID_EDITABLECACHE";
108 public static final String P_ID_REFERENCETYPE = "P_ID_REFERENCETYPE";
109 public static final String P_ID_AUTHORTEAM = "P_ID_AUTHORTEAM";
110 public static final String P_ID_YEAR = "P_ID_YEAR";
111 public static final String P_ID_URI = "P_ID_URI";
112 public static final String P_ID_DATEPUBLISHED = "P_ID_DATEPUBLISHED";
113 public static final String P_ID_TITLE = "P_ID_TITLE";
114 public static final String P_ID_INJOURNAL = "P_ID_INJOURNAL";
115 public static final String P_ID_PAGES = "P_ID_PAGES";
116 public static final String P_ID_SERIES = "P_ID_SERIES";
117 public static final String P_ID_VOLUME = "P_ID_VOLUME";
118 public static final String P_ID_EDITOR = "P_ID_EDITOR";
119 public static final String P_ID_PLACEPUBLISHED = "P_ID_PLACEPUBLISHED";
120 public static final String P_ID_PUBLISHER = "P_ID_PUBLISHER";
121 public static final String P_ID_ISSN = "P_ID_ISSN";
122 public static final String P_ID_INSTITUTION = "P_ID_INSTITUTION";
123 public static final String P_ID_SCHOOL = "P_ID_SCHOOL";
124 public static final String P_ID_INSERIES = "P_ID_INSERIES";
125 public static final String P_ID_SERIESPART = "P_ID_SERIESPART";
126 public static final String P_ID_ISBN = "P_ID_ISBN";
127 public static final String P_ID_ORGANIZATION = "P_ID_ORGANIZATION";
128 public static final String P_ID_PRINTEDUNIT = "P_ID_PRINTEDUNIT";
129 public static final String P_ID_INBOOK = "P_ID_INBOOK";
130 public static final String P_ID_INPROCEEDINGS = "P_ID_INPROCEEDINGS";
131 public static final String P_ID_BIBTEX_ENTRYTYPE = "P_ID_BIBTEX_ENTRYTYPE";
132 public static final String P_ID_JOURNAL = "P_ID_JOURNAL";
133 public static final String P_ID_BOOKTITLE = "P_ID_BOOKTITLE";
134 public static final String P_ID_CHAPTER = "P_ID_CHAPTER";
135 public static final String P_ID_EDITION = "P_ID_EDITION";
136 public static final String P_ID_NUMBER = "P_ID_NUMBER";
137 public static final String P_ID_ANNOTE = "P_ID_ANNOTE";
138 public static final String P_ID_ADDRESS = "P_ID_ADDRESS";
139 public static final String P_ID_HOWPUBLISHED = "P_ID_HOWPUBLISHED";
140 public static final String P_ID_REPORTTYPE = "P_ID_REPORTTYPE";
141 public static final String P_ID_MONTH = "P_ID_MONTH";
142 public static final String P_ID_EPRINT = "P_ID_EPRINT";
143 public static final String P_ID_NOTE = "P_ID_NOTE";
144 public static final String P_ID_CROSSREF = "P_ID_CROSSREF";
145 public static final String P_ID_PROTECT_CACHE = "P_ID_PROTECT_CACHE";
146
147 // Property display keys
148 public static final String P_SEARCH = "001:Search";
149 public static final String P_EDITABLECACHE = "002:Editable Cache";
150 public static final String P_PROTECT_CACHE = "0020:Protect Cache from overwriting?";
151 public static final String P_REFERENCETYPE = "003:Reference Type";
152 public static final String P_AUTHORTEAM = "01:Author Team (Cache)";
153 public static final String P_YEAR = "02:Year";
154 public static final String P_DATEPUBLISHED = "03:Date Published";
155 public static final String P_TITLE = "06:Title";
156 public static final String P_INJOURNAL = "07:In Journal";
157 public static final String P_VOLUME = "10:Volume";
158 public static final String P_EDITION = "110:Edition";
159 public static final String P_SERIES = "11:Series";
160 public static final String P_PAGES = "110:Pages";
161 public static final String P_EDITOR = "12:Editor";
162 public static final String P_PUBLISHER = "13:Publisher";
163 public static final String P_PLACEPUBLISHED = "14:Place Published";
164 public static final String P_ISSN = "15:ISSN";
165 public static final String P_INSTITUTION = "16:Institution";
166 public static final String P_SCHOOL = "17:School";
167 public static final String P_INSERIES = "18:In Series";
168 public static final String P_SERIESPART = "19:Series Part";
169 public static final String P_ISBN = "20:ISBN";
170 public static final String P_URI = "201:URI";
171 public static final String P_ORGANIZATION = "21:Organization";
172 public static final String P_PRINTEDUNIT = "22:Printed Unit";
173 public static final String P_INBOOK = "23:In Book";
174 public static final String P_INPROCEEDINGS = "24:In Proceedings";
175 public static final String P_BIBTEX_ENTRYTYPE = "25:BibTeX Entry Type";
176 public static final String P_JOURNAL = "26:Journal";
177 public static final String P_BOOKTITLE = "27:Book Title";
178 public static final String P_CHAPTER = "28:Chapter";
179 public static final String P_NUMBER = "30:Number";
180 public static final String P_ANNOTE = "31:Annote";
181 public static final String P_ADDRESS = "32:Address";
182 public static final String P_HOWPUBLISHED = "33:How Published";
183 public static final String P_REPORTTYPE = "34:Report Type";
184 public static final String P_MONTH = "35:Month";
185 public static final String P_EPRINT = "36:E-Print";
186 public static final String P_NOTE = "37:Note";
187 public static final String P_CROSSREF = "38:BibTeX Crossref";
188
189 protected static HashMap<Class, String> referenceTypeMap = null;
190
191 private static final String[] P_BIBTEX_ENTRYTYPE_MENU = new String[] {"ARTICLE", "BOOK", "BOOKLET", "INBOOK", "INCOLLECTION", "PROCEEDINGS", "INPROCEEDINGS", "CONFERENCE", "MANUAL", "MASTERTHESIS", "PHDTHESIS", "TECHREPORT", "UNPUBLISHED", "MISC"};
192
193 private static final int CACHE_NOT_PROTECTED = 0;
194 private static final int CACHE_PROTECTED = 1;
195
196 protected void populateReferenceTypes() {
197
198 // LinkedHashMap maintains insertion order
199 referenceTypeMap = new LinkedHashMap<Class, String>();
200
201 referenceTypeMap.put(ReferenceBase.class, "");
202 // referenceTypeMap.put(BibtexReference.class, "BibTeX Reference");
203 referenceTypeMap.put(Article.class, "Article");
204 referenceTypeMap.put(Generic.class, "Generic");
205 referenceTypeMap.put(Patent.class, "Patent");
206 referenceTypeMap.put(PersonalCommunication.class, "Personal Communication");
207 referenceTypeMap.put(CdDvd.class, "CD / DVD");
208 referenceTypeMap.put(Database.class, "Database");
209 referenceTypeMap.put(Journal.class, "Journal");
210 referenceTypeMap.put(Map.class, "Map");
211 referenceTypeMap.put(Book.class, "Book");
212 referenceTypeMap.put(Proceedings.class, "Proceedings");
213 referenceTypeMap.put(PrintSeries.class, "Print Series");
214 referenceTypeMap.put(Report.class, "Report");
215 referenceTypeMap.put(Thesis.class, "Thesis");
216 referenceTypeMap.put(WebPage.class, "Web Page");
217 referenceTypeMap.put(BookSection.class, "Book Section");
218 referenceTypeMap.put(InProceedings.class, "In Proceedings");
219 }
220
221 protected String[] getReferenceTypeArray() {
222 if (referenceTypeMap == null) {
223 populateReferenceTypes();
224 }
225 return referenceTypeMap.values().toArray(new String[] {});
226 }
227
228 protected Set<Class> getReferenceClassSet() {
229 return referenceTypeMap.keySet();
230 }
231
232 public ReferencePropertySource(ReferenceBase reference) {
233
234 // Default type of ReferenceBase is Generic
235 if (reference == null) {
236 reference = Generic.NewInstance();
237 }
238 this.reference = reference;
239
240 initDescriptors();
241 }
242
243 protected void initDescriptors() {
244
245 List<String> displayFields = new ArrayList<String>();
246
247 // Drop-down menu to change reference type
248 displayFields.add(P_ID_REFERENCETYPE);
249
250 // ReferenceBase fields
251 displayFields.add(P_ID_SEARCH);
252 displayFields.add(P_ID_EDITABLECACHE);
253 displayFields.add(P_ID_PROTECT_CACHE);
254 displayFields.add(P_ID_AUTHORTEAM);
255 displayFields.add(P_ID_URI);
256
257 Class referenceClass = reference.getClass();
258
259 if (reference instanceof BibtexReference) {
260
261 displayFields.add(P_ID_BIBTEX_ENTRYTYPE);
262 displayFields.add(P_ID_YEAR);
263 displayFields.add(P_ID_JOURNAL);
264 displayFields.add(P_ID_BOOKTITLE);
265 displayFields.add(P_ID_CHAPTER);
266 displayFields.add(P_ID_TITLE);
267 displayFields.add(P_ID_SERIES);
268 displayFields.add(P_ID_EDITION);
269 displayFields.add(P_ID_VOLUME);
270 displayFields.add(P_ID_NUMBER);
271 displayFields.add(P_ID_PAGES);
272 displayFields.add(P_ID_ANNOTE);
273 displayFields.add(P_ID_EDITOR);
274 displayFields.add(P_ID_INSTITUTION);
275 displayFields.add(P_ID_SCHOOL);
276 displayFields.add(P_ID_ORGANIZATION);
277 displayFields.add(P_ID_PUBLISHER);
278 displayFields.add(P_ID_ADDRESS);
279 displayFields.add(P_ID_HOWPUBLISHED);
280 displayFields.add(P_ID_REPORTTYPE);
281 displayFields.add(P_ID_MONTH);
282 displayFields.add(P_ID_EPRINT);
283 displayFields.add(P_ID_NOTE);
284 displayFields.add(P_ID_CROSSREF);
285 }
286
287 if (reference instanceof StrictReferenceBase) {
288
289 displayFields.add(P_ID_DATEPUBLISHED);
290 displayFields.add(P_ID_TITLE);
291
292 if (referenceClass == Article.class) {
293 displayFields.add(P_ID_INJOURNAL);
294 displayFields.add(P_ID_PAGES);
295 displayFields.add(P_ID_SERIES);
296 displayFields.add(P_ID_VOLUME);
297 }
298
299 if (referenceClass == Generic.class) {
300 displayFields.add(P_ID_PAGES);
301 displayFields.add(P_ID_SERIES);
302 displayFields.add(P_ID_VOLUME);
303 displayFields.add(P_ID_EDITOR);
304 displayFields.add(P_ID_PLACEPUBLISHED);
305 displayFields.add(P_ID_PUBLISHER);
306 }
307
308 if (referenceClass == Patent.class) {
309 // No additional fields
310 }
311
312 if (referenceClass == PersonalCommunication.class) {
313 // No additional fields
314 }
315 if (reference instanceof PublicationBase) {
316
317 displayFields.add(P_ID_PLACEPUBLISHED);
318 displayFields.add(P_ID_PUBLISHER);
319
320 if (referenceClass == CdDvd.class) {
321 // No additional fields
322 }
323
324 if (referenceClass == Database.class) {
325 // No additional fields
326 }
327
328 if (referenceClass == Journal.class) {
329 displayFields.add(P_ID_ISSN);
330 }
331
332 if (referenceClass == Map.class) {
333 // No additional fields
334 }
335
336 if (referenceClass == PrintSeries.class) {
337 displayFields.add(P_ID_SERIES);
338 }
339
340 if (referenceClass == Report.class) {
341 displayFields.add(P_ID_INSTITUTION);
342 }
343
344 if (referenceClass == Thesis.class) {
345 displayFields.add(P_ID_SCHOOL);
346 }
347
348 if (referenceClass == WebPage.class) {
349 // No additional fields
350 }
351
352 if (reference instanceof PrintedUnitBase) {
353
354 displayFields.add(P_ID_EDITOR);
355 displayFields.add(P_ID_INSERIES);
356 displayFields.add(P_ID_PAGES);
357 displayFields.add(P_ID_SERIESPART);
358 displayFields.add(P_ID_VOLUME);
359
360 if (referenceClass == Book.class) {
361 displayFields.add(P_ID_ISBN);
362 displayFields.add(P_ID_EDITION);
363 }
364
365 if (referenceClass == Proceedings.class) {
366 displayFields.add(P_ID_ORGANIZATION);
367 }
368 }
369 }
370
371 if (reference instanceof SectionBase) {
372
373 displayFields.add(P_ID_PAGES);
374 displayFields.add(P_ID_PRINTEDUNIT);
375
376 if (referenceClass == BookSection.class) {
377 displayFields.add(P_ID_INBOOK);
378 }
379
380 if (referenceClass == InProceedings.class) {
381 displayFields.add(P_ID_INPROCEEDINGS);
382 }
383 }
384 }
385
386 for (String field : displayFields) {
387 addDescriptor(field);
388 }
389 }
390
391 protected Vector<PropertyDescriptor> descriptors = new Vector<PropertyDescriptor>();
392
393 protected void addDescriptor(String id) {
394
395 // Reference search
396 if (id.equals(P_ID_SEARCH)) {
397 descriptors.addElement(
398 new ReferenceSearchDescriptor(P_ID_SEARCH, P_SEARCH, getSearchType()) {
399 protected void saveReference(ReferenceBase reference) {
400 setPropertyValue(P_ID_SEARCH, reference);
401 }
402 });
403 }
404
405 // Editable cache
406 if (id.equals(P_ID_EDITABLECACHE)) {
407 descriptors.addElement(
408 new TextPropertyDescriptor(P_ID_EDITABLECACHE, P_EDITABLECACHE));
409 }
410
411 // Protect cache?
412 if (id.equals(P_ID_PROTECT_CACHE)) {
413 descriptors.addElement(
414 new ComboBoxPropertyDescriptor(P_ID_PROTECT_CACHE, P_PROTECT_CACHE,
415 new String[] {"no", "yes"}));
416 }
417
418 // Reference type
419 if (id.equals(P_ID_REFERENCETYPE)) {
420 descriptors.addElement(createReferenceTypeDescriptor());
421 }
422
423 // Author team
424 if (id.equals(P_ID_AUTHORTEAM)) {
425 descriptors.addElement(
426 new TextPropertyDescriptor(P_ID_AUTHORTEAM, P_AUTHORTEAM));
427 }
428
429 // Year
430 if (id.equals(P_ID_YEAR)) {
431 descriptors.addElement(
432 new TextPropertyDescriptor(P_ID_YEAR, P_YEAR));
433 }
434
435 // Date published
436 if (id.equals(P_ID_DATEPUBLISHED)) {
437
438 // TimePeriodPropertySource returns TimePeriod.getYear() - make this editable
439 TextPropertyDescriptor yearDescriptor = new TextPropertyDescriptor(
440 P_ID_DATEPUBLISHED, P_DATEPUBLISHED);
441 yearDescriptor.setValidator(new YearValidator());
442 descriptors.addElement(yearDescriptor);
443 }
444
445 // URI
446 if (id.equals(P_ID_URI)) {
447 descriptors.addElement(
448 new TextPropertyDescriptor(P_ID_URI, P_URI));
449 }
450
451 // Title
452 if (id.equals(P_ID_TITLE)) {
453 descriptors.addElement(
454 new TextPropertyDescriptor(P_ID_TITLE, P_TITLE));
455 }
456
457 // In journal
458 if (id.equals(P_ID_INJOURNAL)) {
459 descriptors.addElement(
460 new TextPropertyDescriptor(P_ID_INJOURNAL, P_INJOURNAL));
461 }
462
463 // Pages
464 if (id.equals(P_ID_PAGES)) {
465 descriptors.addElement(
466 new TextPropertyDescriptor(P_ID_PAGES, P_PAGES));
467 }
468
469 // Series
470 if (id.equals(P_ID_SERIES)) {
471 descriptors.addElement(
472 new TextPropertyDescriptor(P_ID_SERIES, P_SERIES));
473 }
474
475 // Volume
476 if (id.equals(P_ID_VOLUME )) {
477 descriptors.addElement(
478 new TextPropertyDescriptor(P_ID_VOLUME, P_VOLUME));
479 }
480
481 // Editor
482 if (id.equals(P_ID_EDITOR)) {
483 descriptors.addElement(
484 new TextPropertyDescriptor(P_ID_EDITOR, P_EDITOR));
485 }
486
487 // Edition
488 if (id.equals(P_ID_EDITION)) {
489 descriptors.addElement(
490 new TextPropertyDescriptor(P_ID_EDITION, P_EDITION));
491 }
492
493 // Place published
494 if (id.equals(P_ID_PLACEPUBLISHED)) {
495 descriptors.addElement(
496 new TextPropertyDescriptor(P_ID_PLACEPUBLISHED, P_PLACEPUBLISHED));
497 }
498
499 // Publisher
500 if (id.equals(P_ID_PUBLISHER)) {
501 descriptors.addElement(
502 new TextPropertyDescriptor(P_ID_PUBLISHER, P_PUBLISHER));
503 }
504
505 // ISSN
506 if (id.equals(P_ID_ISSN)) {
507 descriptors.addElement(
508 new TextPropertyDescriptor(P_ID_ISSN, P_ISSN));
509 }
510
511 // Institution
512 if (id.equals(P_ID_INSTITUTION)) {
513 descriptors.addElement(
514 new TextPropertyDescriptor(P_ID_INSTITUTION, P_INSTITUTION));
515 }
516
517 // School
518 if (id.equals(P_ID_SCHOOL)) {
519 descriptors.addElement(
520 new TextPropertyDescriptor(P_ID_SCHOOL, P_SCHOOL));
521 }
522
523 // In series
524 if (id.equals(P_ID_INSERIES)) {
525 descriptors.addElement(
526 new TextPropertyDescriptor(P_ID_INSERIES, P_INSERIES));
527 }
528
529 // Series part
530 if (id.equals(P_ID_SERIESPART)) {
531 descriptors.addElement(
532 new TextPropertyDescriptor(P_ID_SERIESPART, P_SERIESPART));
533 }
534
535 // ISBN
536 if (id.equals(P_ID_ISBN)) {
537 descriptors.addElement(
538 new TextPropertyDescriptor(P_ID_ISBN, P_ISBN));
539 }
540
541 // Organization
542 if (id.equals(P_ID_ORGANIZATION)) {
543 descriptors.addElement(
544 new TextPropertyDescriptor(P_ID_ORGANIZATION, P_ORGANIZATION));
545 }
546
547 // Printed unit
548 if (id.equals(P_ID_PRINTEDUNIT)) {
549 descriptors.addElement(
550 new TextPropertyDescriptor(P_ID_PRINTEDUNIT, P_PRINTEDUNIT));
551 }
552
553 // In book
554 if (id.equals(P_ID_INBOOK)) {
555 descriptors.addElement(
556 new TextPropertyDescriptor(P_ID_INBOOK, P_INBOOK));
557 }
558
559 // Bibtex entry type
560 if (id.equals(P_ID_BIBTEX_ENTRYTYPE)) {
561 descriptors.addElement(
562 new ComboBoxPropertyDescriptor(P_ID_BIBTEX_ENTRYTYPE, P_BIBTEX_ENTRYTYPE, P_BIBTEX_ENTRYTYPE_MENU));
563 }
564 }
565
566 /**
567 * The default implementation of <code>ReferencePropertySource</code> will
568 * search all <code>ReferenceBase</code> classes.
569 *
570 * @return
571 */
572 protected int getSearchType() {
573 return IReferenceSearch.BIBREF;
574 }
575
576 /**
577 * The default implementation of <code>ReferencePropertySource</code> will show
578 * a drop-down of reference types, but subclasses may want to show a non-editable
579 * text descriptor of the reference type.
580 */
581 protected PropertyDescriptor createReferenceTypeDescriptor() {
582 return new ComboBoxPropertyDescriptor(
583 P_ID_REFERENCETYPE, P_REFERENCETYPE, getReferenceTypeArray());
584 }
585
586 /* (non-Javadoc)
587 * @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
588 */
589 public Object getEditableValue() {
590 return CdmUtils.Nz(reference.getTitleCache());
591 }
592
593 /* (non-Javadoc)
594 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
595 */
596 public IPropertyDescriptor[] getPropertyDescriptors() {
597 return (IPropertyDescriptor[]) descriptors.toArray(
598 new IPropertyDescriptor[descriptors.size()]);
599 }
600
601 /* (non-Javadoc)
602 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
603 */
604 public Object getPropertyValue(Object id) {
605
606 // Reference Type: get integer index of drop-down menu
607 if (id.equals(P_ID_REFERENCETYPE)) {
608 Class referenceClass = reference.getClass();
609 int menuIndex = 0;
610 // for (Class clazz : referenceTypeMap.keySet()) {
611 for (Class clazz : getReferenceClassSet()) {
612 if (clazz == referenceClass) {
613 return menuIndex;
614 }
615 menuIndex++;
616 }
617 return 0;
618 }
619
620 // Editable cache
621 if (id.equals(P_ID_EDITABLECACHE)) {
622 return (CdmUtils.Nz(reference.getTitleCache()));
623 }
624
625 // Protect cache?
626 if (id.equals(P_ID_PROTECT_CACHE)) {
627 if (reference.isProtectedTitleCache()) {
628 return CACHE_PROTECTED;
629 } else {
630 return CACHE_NOT_PROTECTED;
631 }
632 }
633
634 // Author Team: for now, just edit the cache
635 // TODO AuthorTeamPropertySource
636 if (id.equals(P_ID_AUTHORTEAM)) {
637 TeamOrPersonBase authorTeam = reference.getAuthorTeam();
638
639 if (authorTeam == null) {
640 return "";
641 }
642
643 return CdmUtils.Nz(authorTeam.getTitleCache());
644 }
645
646 // Year
647 if (id.equals(P_ID_YEAR)) {
648 return CdmUtils.Nz(reference.getYear());
649 }
650
651 // URI
652 if (id.equals(P_ID_URI)) {
653 return CdmUtils.Nz(reference.getUri());
654 }
655
656 // Date published
657 if (id.equals(P_ID_DATEPUBLISHED)) {
658 TimePeriod datePublished = (TimePeriod) invokeMethod(reference, "getDatePublished", null);
659
660 if (datePublished == null) {
661 datePublished = TimePeriod.NewInstance();
662 }
663
664 TimePeriodPropertySource timePeriodPropertySource =
665 new TimePeriodPropertySource(datePublished);
666 timePeriodPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
667 public void propertyChange(PropertyChangeEvent evt) {
668 if (reference instanceof StrictReferenceBase && evt.getNewValue() instanceof TimePeriod) {
669 ((StrictReferenceBase) reference).setDatePublished((TimePeriod) evt.getNewValue());
670 }
671 }
672 });
673 return timePeriodPropertySource;
674 }
675
676 // Title: used by StrictReferenceBase
677 if (id.equals(P_ID_TITLE)) {
678 String title = (String) invokeMethod(reference, "getTitle", null);
679 return CdmUtils.Nz(title);
680 }
681
682 // InJournal: return an instance of ReferencePropertySource
683 if (id.equals(P_ID_INJOURNAL)) {
684
685 Journal inJournal = (Journal) invokeMethod(reference, "getInJournal", null);
686
687 if (inJournal == null) {
688 inJournal = Journal.NewInstance();
689 }
690
691 ReferencePropertySource bibRefPropertySource = new SingleRefTypePropertySource(
692 inJournal, SingleRefTypePropertySource.JOURNAL);
693 bibRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
694 public void propertyChange(PropertyChangeEvent evt) {
695 if (reference instanceof Article && evt.getNewValue() instanceof Journal) {
696 ((Article) reference).setInJournal((Journal) evt.getNewValue());
697 }
698 }
699 });
700 return bibRefPropertySource;
701 }
702
703 // Pages
704 if (id.equals(P_ID_PAGES)) {
705 String pages = (String) invokeMethod(reference, "getPages", null);
706 return CdmUtils.Nz(pages);
707 }
708
709 // Series
710 if (id.equals(P_ID_SERIES)) {
711 String series = (String) invokeMethod(reference, "getSeries", null);
712 return CdmUtils.Nz(series);
713 }
714
715 // Volume
716 if (id.equals(P_ID_VOLUME)) {
717 String volume = (String) invokeMethod(reference, "getVolume", null);
718 return CdmUtils.Nz(volume);
719 }
720
721 // Editor
722 if (id.equals(P_ID_EDITOR)) {
723 String editor = (String) invokeMethod(reference, "getEditor", null);
724 return CdmUtils.Nz(editor);
725 }
726
727 // Edition
728 if (id.equals(P_ID_EDITION)) {
729 String edition = (String) invokeMethod(reference, "getEdition", null);
730 return CdmUtils.Nz(edition);
731 }
732
733 // Place published
734 if (id.equals(P_ID_PLACEPUBLISHED)) {
735 String placePublished = (String) invokeMethod(reference, "getPlacePublished", null);
736 return CdmUtils.Nz(placePublished);
737 }
738
739 // Publisher
740 if (id.equals(P_ID_PUBLISHER)) {
741 String publisher = (String) invokeMethod(reference, "getPublisher", null);
742 return CdmUtils.Nz(publisher);
743 }
744
745 // ISSN
746 if (id.equals(P_ID_ISSN)) {
747 String issn = (String) invokeMethod(reference, "getIssn", null);
748 return CdmUtils.Nz(issn);
749 }
750
751 // Institution
752 if (id.equals(P_ID_INSTITUTION)) {
753 String institution = (String) invokeMethod(reference, "getInstitution", null);
754 return CdmUtils.Nz(institution);
755 }
756
757 // In series
758 if (id.equals(P_ID_INSERIES)) {
759
760 }
761
762 // ISBN
763 if (id.equals(P_ID_ISBN)) {
764 String isbn = (String) invokeMethod(reference, "getIsbn", null);
765 return CdmUtils.Nz(isbn);
766 }
767
768 // Organization
769 if (id.equals(P_ID_ORGANIZATION)) {
770 String organization = (String) invokeMethod(reference, "getOrganization", null);
771 return CdmUtils.Nz(organization);
772 }
773
774 // In book
775 if (id.equals(P_ID_INBOOK)) {
776
777 Book inBook = (Book) invokeMethod(reference, "getInBook", null);
778
779 if (inBook == null) {
780 inBook = Book.NewInstance();
781 }
782
783 ReferencePropertySource bibRefPropertySource = new SingleRefTypePropertySource(
784 inBook, SingleRefTypePropertySource.BOOK);
785 bibRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
786 public void propertyChange(PropertyChangeEvent evt) {
787 if (reference instanceof BookSection && evt.getNewValue() instanceof Book) {
788 ((BookSection) reference).setInBook((Book) evt.getNewValue());
789 }
790 }
791 });
792 return bibRefPropertySource;
793 }
794
795 // Bibtex entry type
796 if (id.equals(P_ID_BIBTEX_ENTRYTYPE)) {
797
798 }
799
800 return "";
801 }
802
803 /**
804 * Executes <code>methodName</code> on <code>obj</code> with
805 * the argument <code>arg</code>.
806 * <p>
807 * On failure, returns <code>null</code>.
808 * <p>
809 * NOTE: both <code>Class.getMethod()</code> and <code>Method.invoke()</code>
810 * can be called with the <code>Object... args</code> approach, which allows
811 * the user to pass in a varying number of arguments. To keep it simple, and since
812 * this is usually only getters or setters, we are using only one argument.
813 * @param obj
814 * @param methodName
815 * @param args
816 * @return
817 */
818 private Object invokeMethod(Object obj, String methodName, Object arg) {
819 try {
820 Method method = null;
821 if (arg == null) {
822 method = obj.getClass().getMethod(methodName);
823 return method.invoke(obj);
824 } else {
825 method = obj.getClass().getMethod(methodName, arg.getClass());
826 return method.invoke(obj, arg);
827 }
828 } catch (SecurityException e) {
829 logger.error(e.getMessage());
830 } catch (IllegalArgumentException e) {
831 logger.error(e.getMessage());
832 } catch (NoSuchMethodException e) {
833 logger.error(e.getMessage());
834 } catch (IllegalAccessException e) {
835 logger.error(e.getMessage());
836 } catch (InvocationTargetException e) {
837 logger.error(e.getMessage());
838 }
839 return null;
840 }
841
842 /* (non-Javadoc)
843 * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
844 */
845 public boolean isPropertySet(Object id) {
846 return false;
847 }
848
849 /* (non-Javadoc)
850 * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
851 */
852 public void resetPropertyValue(Object id) {}
853
854 /* (non-Javadoc)
855 * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
856 */
857 public void setPropertyValue(Object id, Object value) {
858
859 // Search result
860 if (id.equals(P_ID_SEARCH)) {
861 if (value instanceof ReferenceBase) {
862 reference = (ReferenceBase) value;
863 }
864 }
865
866 // Protect cache?
867 if (id.equals(P_ID_PROTECT_CACHE)) {
868 if (((Integer) value).intValue() == CACHE_PROTECTED) {
869 reference.setProtectedTitleCache(true);
870 } else {
871 reference.setProtectedTitleCache(false);
872 }
873 }
874
875 // Reference Type
876 if (id.equals(P_ID_REFERENCETYPE)) {
877
878 // NOTE: this code will only be reached if user actually changes choice in reference type
879 // dropdown list, not if focus is merely gained and lost without changing the value
880
881 // Grab reference's title cache
882 String oldTitleCache = reference.getTitleCache();
883
884 // Get reference's class
885 int menuIndex;
886 try {
887 menuIndex = ((Integer) value).intValue();
888 } catch (ClassCastException e) {
889 // Leave method / no change on class cast error
890 logger.error(e.getMessage());
891 return;
892 }
893 Class referenceClass = (Class)(getReferenceClassSet().toArray())[menuIndex];
894
895 // Make a new reference using the class
896 reference = makeNewReference(referenceClass);
897
898 // Set new reference's title cache
899 reference.setTitleCache(oldTitleCache);
900 }
901
902 // Author Team
903 if (id.equals(P_ID_AUTHORTEAM)) {
904 TeamOrPersonBase authorTeam = reference.getAuthorTeam();
905 if (authorTeam == null) {
906 authorTeam = Team.NewInstance();
907 reference.setAuthorTeam(authorTeam);
908 }
909 try {
910 authorTeam.setTitleCache((String) value);
911 } catch (ClassCastException e) {
912 // Leave method / no change on class cast error
913 logger.error(e.getMessage());
914 return;
915 }
916 }
917
918 // Citation
919 if (id.equals(P_ID_URI)) {
920 String uri = (String) value;
921 reference.setUri(uri);
922 }
923
924 // Year - only set directly by Bibtex refs
925 if (id.equals(P_ID_YEAR)) {
926 String year = (String) value;
927 if (reference instanceof BibtexReference) {
928 ((BibtexReference) reference).setYear(year);
929 }
930 }
931
932 // Title: used by StrictReferenceBase
933 if (id.equals(P_ID_TITLE)) {
934 String title = null;
935 try {
936 title = (String) value;
937 } catch (ClassCastException e) {
938 // Leave method / no change on class cast error
939 logger.error(e.getMessage());
940 return;
941 }
942 invokeMethod(reference, "setTitle", title);
943 }
944
945 // Pages
946 if (id.equals(P_ID_PAGES)) {
947 invokeMethod(reference, "setPages", (String) value);
948 }
949
950 // Series
951 if (id.equals(P_ID_SERIES)) {
952 invokeMethod(reference, "setSeries", (String) value);
953 }
954
955 // Volume
956 if (id.equals(P_ID_VOLUME)) {
957 invokeMethod(reference, "setVolume", (String) value);
958 }
959
960 // Editor
961 if (id.equals(P_ID_EDITOR)) {
962 invokeMethod(reference, "setEditor", (String) value);
963 }
964
965 // Edition
966 if (id.equals(P_ID_EDITION)) {
967 invokeMethod(reference, "setEdition", (String) value);
968 }
969
970 // Place published
971 if (id.equals(P_ID_PLACEPUBLISHED)) {
972 invokeMethod(reference, "setPlacePublished", (String) value);
973 }
974
975 // Publisher
976 if (id.equals(P_ID_PUBLISHER)) {
977 invokeMethod(reference, "setPublisher", (String) value);
978 }
979
980 // ISSN
981 if (id.equals(P_ID_ISSN)) {
982 invokeMethod(reference, "setIssn", (String) value);
983 }
984
985 // Institution
986 if (id.equals(P_ID_INSTITUTION)) {
987 invokeMethod(reference, "setInstitution", (String) value);
988 }
989
990 // ISBN
991 if (id.equals(P_ID_ISBN)) {
992 invokeMethod(reference, "setIsbn", (String) value);
993 }
994
995 // Organization
996 if (id.equals(P_ID_ORGANIZATION)) {
997 invokeMethod(reference, "setOrganization", (String) value);
998 }
999
1000 // In book
1001 if (id.equals(P_ID_INBOOK)) {
1002 Book inBook = (Book) invokeMethod(reference, "getInBook", null);
1003 if (inBook == null) {
1004 inBook = Book.NewInstance();
1005 invokeMethod(reference, "setInBook", inBook);
1006 }
1007 inBook.setTitleCache((String) value);
1008 }
1009
1010 // Date published
1011 if (id.equals(P_ID_DATEPUBLISHED)) {
1012
1013 if (!(reference instanceof StrictReferenceBase)) {
1014 return;
1015 }
1016
1017 if (value instanceof String) {
1018 String year = (String) value;
1019 TimePeriod yearsPublished = null;
1020
1021 // If not empty, format is either "xxxx" or "xxxx-xxxx", thanks to validator
1022 if (!year.equals("")) {
1023
1024 // Convert to a TimePeriod
1025 yearsPublished = CdmUtil.convertTimePeriod(year);
1026
1027 // Update reference's dataPublished field
1028 TimePeriod datePublished = ((StrictReferenceBase) reference).getDatePublished();
1029
1030 if (datePublished == null) {
1031 ((StrictReferenceBase) reference).setDatePublished(yearsPublished);
1032 } else {
1033
1034 // Any months or days should be left as is - only update years
1035 datePublished.setStartYear(yearsPublished.getStartYear());
1036 datePublished.setEndYear(yearsPublished.getEndYear());
1037 }
1038 } else {
1039 ((StrictReferenceBase) reference).setDatePublished(null);
1040 }
1041
1042
1043 }
1044 }
1045
1046 // Editable cache
1047 if (id.equals(P_ID_EDITABLECACHE)) {
1048 reference.setTitleCache((String) value);
1049 } else {
1050 reference.setTitleCache(reference.generateTitle(), reference.isProtectedTitleCache());
1051 }
1052
1053 propertyChangeSupport.firePropertyChange(ITaxEditorConstants.PROPERTY_SHEET_CHANGE, null, reference);
1054 }
1055
1056 /**
1057 * Takes a <code>referenceClass</code>, then executes either its <code>NewInstance()</code>
1058 * method or its constructor. Puts the resulting object in <code>this.reference</code> and
1059 * returns it.
1060 * <p>
1061 * If unsuccessful, <code>this.reference</code> keeps its old value and is returned.
1062 * @param referenceClass
1063 * @return
1064 */
1065 private ReferenceBase makeNewReference(Class referenceClass) {
1066
1067 // Check whether the class has a method "NewInstance()";
1068 try {
1069 Method method = referenceClass.getMethod("NewInstance", null);
1070 reference = (ReferenceBase) method.invoke(null, null);
1071 } catch (NoSuchMethodException e) {
1072 try {
1073 // If not, use its constructor
1074 Constructor constructor = referenceClass.getConstructor(null);
1075 reference = (ReferenceBase) constructor.newInstance(null);
1076 } catch (SecurityException e1) {
1077 e1.printStackTrace();
1078 } catch (NoSuchMethodException e1) {
1079 e1.printStackTrace();
1080 } catch (IllegalArgumentException e1) {
1081 e1.printStackTrace();
1082 } catch (InstantiationException e1) {
1083 e1.printStackTrace();
1084 } catch (IllegalAccessException e1) {
1085 e1.printStackTrace();
1086 } catch (InvocationTargetException e1) {
1087 e1.printStackTrace();
1088 }
1089 } catch (SecurityException e) {
1090 e.printStackTrace();
1091 } catch (IllegalArgumentException e) {
1092 e.printStackTrace();
1093 } catch (IllegalAccessException e) {
1094 e.printStackTrace();
1095 } catch (InvocationTargetException e) {
1096 e.printStackTrace();
1097 }
1098
1099 return reference;
1100 }
1101
1102 private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1103
1104 public void addPropertyChangeListener(
1105 PropertyChangeListener listener) {
1106 propertyChangeSupport.addPropertyChangeListener(listener);
1107 }
1108 }