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