Project

General

Profile

Download (38.1 KB) Statistics
| Branch: | Tag: | Revision:
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.CdmBase;
36
import eu.etaxonomy.cdm.model.common.TimePeriod;
37
import eu.etaxonomy.cdm.model.reference.Article;
38
import eu.etaxonomy.cdm.model.reference.BibtexReference;
39
import eu.etaxonomy.cdm.model.reference.Book;
40
import eu.etaxonomy.cdm.model.reference.BookSection;
41
import eu.etaxonomy.cdm.model.reference.CdDvd;
42
import eu.etaxonomy.cdm.model.reference.Database;
43
import eu.etaxonomy.cdm.model.reference.Generic;
44
import eu.etaxonomy.cdm.model.reference.InProceedings;
45
import eu.etaxonomy.cdm.model.reference.Journal;
46
import eu.etaxonomy.cdm.model.reference.Map;
47
import eu.etaxonomy.cdm.model.reference.Patent;
48
import eu.etaxonomy.cdm.model.reference.PersonalCommunication;
49
import eu.etaxonomy.cdm.model.reference.PrintSeries;
50
import eu.etaxonomy.cdm.model.reference.PrintedUnitBase;
51
import eu.etaxonomy.cdm.model.reference.Proceedings;
52
import eu.etaxonomy.cdm.model.reference.PublicationBase;
53
import eu.etaxonomy.cdm.model.reference.ReferenceBase;
54
import eu.etaxonomy.cdm.model.reference.Report;
55
import eu.etaxonomy.cdm.model.reference.SectionBase;
56
import eu.etaxonomy.cdm.model.reference.StrictReferenceBase;
57
import eu.etaxonomy.cdm.model.reference.Thesis;
58
import eu.etaxonomy.cdm.model.reference.WebPage;
59
import eu.etaxonomy.taxeditor.propertysheet.TimePeriodPropertySource;
60
import eu.etaxonomy.taxeditor.propertysheet.YearValidator;
61
import eu.etaxonomy.taxeditor.store.model.Resources;
62
import eu.etaxonomy.taxeditor.store.model.TimeUtil;
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 = "Search";
149
	public static final String P_EDITABLECACHE = "Editable Cache";
150
	public static final String P_PROTECT_CACHE = "Protect Cache from overwriting?";
151
	public static final String P_REFERENCETYPE = "Reference Type";
152
	public static final String P_AUTHORTEAM = "Author Team (Cache)";
153
	public static final String P_YEAR = "Year";
154
	public static final String P_DATEPUBLISHED = "Date Published";
155
	public static final String P_TITLE = "Title";
156
	public static final String P_INJOURNAL = "In Journal";
157
	public static final String P_VOLUME = "Volume";
158
	public static final String P_EDITION = "Edition";
159
	public static final String P_SERIES = "Series";
160
	public static final String P_PAGES = "Pages";
161
	public static final String P_EDITOR = "Editor";
162
	public static final String P_PUBLISHER = "Publisher";
163
	public static final String P_PLACEPUBLISHED = "Place Published";
164
	public static final String P_ISSN = "ISSN";
165
	public static final String P_INSTITUTION = "Institution";
166
	public static final String P_SCHOOL = "School";
167
	public static final String P_INSERIES = "In Series";
168
	public static final String P_SERIESPART = "Series Part";
169
	public static final String P_ISBN = "ISBN";
170
	public static final String P_URI = "URI";
171
	public static final String P_ORGANIZATION = "Organization";
172
	public static final String P_PRINTEDUNIT = "Printed Unit";
173
	public static final String P_INBOOK = "In Book";
174
	public static final String P_INPROCEEDINGS = "In Proceedings";
175
	public static final String P_BIBTEX_ENTRYTYPE = "BibTeX Entry Type";
176
	public static final String P_JOURNAL = "Journal";
177
	public static final String P_BOOKTITLE = "Book Title";
178
	public static final String P_CHAPTER = "Chapter";
179
	public static final String P_NUMBER = "Number";
180
	public static final String P_ANNOTE = "Annote";
181
	public static final String P_ADDRESS = "Address";
182
	public static final String P_HOWPUBLISHED = "How Published";
183
	public static final String P_REPORTTYPE = "Report Type";
184
	public static final String P_MONTH = "Month";
185
	public static final String P_EPRINT = "E-Print";
186
	public static final String P_NOTE = "Note";
187
	public static final String P_CROSSREF = "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 = CdmBase.deproxy(object, clazz)reference;
239
		this.reference = reference;
240

    
241
		initDescriptors();
242
	}
243

    
244
	protected void initDescriptors() {
245
		
246
		List<String> displayFields = new ArrayList<String>();
247
	
248
		// Drop-down menu to change reference type
249
		displayFields.add(P_ID_REFERENCETYPE);
250
		
251
		// ReferenceBase fields
252
		displayFields.add(P_ID_SEARCH);
253
		displayFields.add(P_ID_EDITABLECACHE);
254
		displayFields.add(P_ID_PROTECT_CACHE);
255
		displayFields.add(P_ID_AUTHORTEAM);
256
		displayFields.add(P_ID_URI);
257
		
258
		Class referenceClass = reference.getClass();
259
		
260
//		if (reference instanceof BibtexReference) {
261
//						
262
//			displayFields.add(P_ID_BIBTEX_ENTRYTYPE);
263
//			displayFields.add(P_ID_YEAR);
264
//			displayFields.add(P_ID_JOURNAL);
265
//			displayFields.add(P_ID_BOOKTITLE);
266
//			displayFields.add(P_ID_CHAPTER);			
267
//			displayFields.add(P_ID_TITLE);
268
//			displayFields.add(P_ID_SERIES);
269
//			displayFields.add(P_ID_EDITION);
270
//			displayFields.add(P_ID_VOLUME);
271
//			displayFields.add(P_ID_NUMBER);
272
//			displayFields.add(P_ID_PAGES);
273
//			displayFields.add(P_ID_ANNOTE);
274
//			displayFields.add(P_ID_EDITOR);
275
//			displayFields.add(P_ID_INSTITUTION);
276
//			displayFields.add(P_ID_SCHOOL);
277
//			displayFields.add(P_ID_ORGANIZATION);
278
//			displayFields.add(P_ID_PUBLISHER);
279
//			displayFields.add(P_ID_ADDRESS);
280
//			displayFields.add(P_ID_HOWPUBLISHED);
281
//			displayFields.add(P_ID_REPORTTYPE);
282
//			displayFields.add(P_ID_MONTH);
283
//			displayFields.add(P_ID_EPRINT);
284
//			displayFields.add(P_ID_NOTE);
285
//			displayFields.add(P_ID_CROSSREF);
286
//		}
287
	
288
		if (reference instanceof StrictReferenceBase) {
289
			
290
			displayFields.add(P_ID_DATEPUBLISHED);
291
			displayFields.add(P_ID_TITLE);
292
	
293
			if (referenceClass == Article.class) {
294
				displayFields.add(P_ID_INJOURNAL);
295
				displayFields.add(P_ID_PAGES);
296
				displayFields.add(P_ID_SERIES);
297
				displayFields.add(P_ID_VOLUME);
298
			}
299
	
300
			if (referenceClass == Generic.class) {
301
				displayFields.add(P_ID_PAGES);
302
				displayFields.add(P_ID_SERIES);
303
				displayFields.add(P_ID_VOLUME);
304
				displayFields.add(P_ID_EDITOR);
305
//				displayFields.add(P_ID_PLACEPUBLISHED);
306
//				displayFields.add(P_ID_PUBLISHER);
307
			}			
308
			
309
			if (referenceClass == Patent.class) {
310
				// No additional fields
311
			}
312
			
313
			if (referenceClass == PersonalCommunication.class) {
314
				// No additional fields				
315
			}
316
			if (reference instanceof PublicationBase) {
317
	
318
				displayFields.add(P_ID_PLACEPUBLISHED);
319
				displayFields.add(P_ID_PUBLISHER);
320
				
321
				if (referenceClass == CdDvd.class) {
322
					// No additional fields							
323
				}
324
				
325
				if (referenceClass == Database.class) {
326
					// No additional fields					
327
				}
328
				
329
				if (referenceClass == Journal.class) {	
330
					displayFields.add(P_ID_ISSN);
331
				}
332
	
333
				if (referenceClass == Map.class) {
334
					// No additional fields					
335
				}				
336
				
337
				if (referenceClass == PrintSeries.class) {
338
					displayFields.add(P_ID_SERIES);					
339
				}
340
				
341
				if (referenceClass == Report.class) {
342
					displayFields.add(P_ID_INSTITUTION);					
343
				}
344
				
345
				if (referenceClass == Thesis.class) {
346
					displayFields.add(P_ID_SCHOOL);						
347
				}
348
				
349
				if (referenceClass == WebPage.class) {
350
					// No additional fields		
351
				}
352
				
353
				if (reference instanceof PrintedUnitBase) {
354
					
355
					displayFields.add(P_ID_EDITOR);
356
					displayFields.add(P_ID_INSERIES);
357
					displayFields.add(P_ID_PAGES);
358
					displayFields.add(P_ID_SERIESPART);
359
					displayFields.add(P_ID_VOLUME);
360
					
361
					if (referenceClass == Book.class) {
362
						displayFields.add(P_ID_ISBN);
363
						displayFields.add(P_ID_EDITION);
364
					}
365
					
366
					if (referenceClass == Proceedings.class) {
367
						displayFields.add(P_ID_ORGANIZATION);							
368
					}
369
				}
370
			}
371
			
372
			if (reference instanceof SectionBase) {
373
				
374
				displayFields.add(P_ID_PAGES);	
375
				displayFields.add(P_ID_PRINTEDUNIT);
376
				
377
				if (referenceClass == BookSection.class) {
378
					displayFields.add(P_ID_INBOOK);
379
				}
380
				
381
				if (referenceClass == InProceedings.class) {
382
					displayFields.add(P_ID_INPROCEEDINGS);					
383
				}
384
			}
385
		}
386
		
387
		// There was a problem with duplicate descriptors in the above code
388
		List<String> displayFieldsTemp = new ArrayList<String>();
389
		for (String field : displayFields) {
390
			if (displayFieldsTemp.contains(field)) {
391
				continue;
392
			}
393
			addDescriptor(field);
394
			displayFieldsTemp.add(field);
395
		}
396
	}
397

    
398
	protected Vector<PropertyDescriptor> descriptors = new Vector<PropertyDescriptor>();
399
	
400
	protected void addDescriptor(String id) {
401
		
402
		// Reference search
403
		if (id.equals(P_ID_SEARCH)) {
404
			descriptors.addElement(
405
					new ReferenceSearchDescriptor(P_ID_SEARCH, P_SEARCH, getSearchType()) {
406
						protected void saveReference(ReferenceBase reference) {
407
							setPropertyValue(P_ID_SEARCH, reference);
408
						}
409
			});
410
		}
411
		
412
		// Editable cache
413
		if (id.equals(P_ID_EDITABLECACHE)) {
414
			descriptors.addElement(
415
					new TextPropertyDescriptor(P_ID_EDITABLECACHE, P_EDITABLECACHE));
416
		}
417
		
418
		// Protect cache?
419
		if (id.equals(P_ID_PROTECT_CACHE)) {
420
			descriptors.addElement(
421
					new ComboBoxPropertyDescriptor(P_ID_PROTECT_CACHE, P_PROTECT_CACHE, 
422
							new String[] {"no", "yes"}));
423
//			descriptors.addElement(
424
//					new CheckboxPropertyDescriptor(P_ID_PROTECT_CACHE, P_PROTECT_CACHE));			
425
		}
426
		
427
		// Reference type
428
		if (id.equals(P_ID_REFERENCETYPE)) {
429
			descriptors.addElement(createReferenceTypeDescriptor());
430
		}
431
		
432
		boolean isProtectedCache = reference.isProtectedTitleCache();
433
		
434
		// Author team
435
		if (id.equals(P_ID_AUTHORTEAM)) {
436
			descriptors.addElement(
437
					isProtectedCache?
438
							new PropertyDescriptor(P_ID_AUTHORTEAM, P_AUTHORTEAM) :
439
							new TextPropertyDescriptor(P_ID_AUTHORTEAM, P_AUTHORTEAM));			
440
		}
441
		
442
		// Year
443
		if (id.equals(P_ID_YEAR)) {
444
			descriptors.addElement(
445
					isProtectedCache?
446
							new PropertyDescriptor(P_ID_YEAR, P_YEAR) :
447
							new TextPropertyDescriptor(P_ID_YEAR, P_YEAR));
448
		}
449
		
450
		// Date published
451
		if (id.equals(P_ID_DATEPUBLISHED)) {
452
			
453
			// TimePeriodPropertySource returns TimePeriod.getYear() - make this editable
454
			if (isProtectedCache) {
455
				descriptors.addElement(new PropertyDescriptor(
456
						P_ID_DATEPUBLISHED, P_DATEPUBLISHED));
457
			} else {
458
				TextPropertyDescriptor yearDescriptor = new TextPropertyDescriptor(
459
						P_ID_DATEPUBLISHED, P_DATEPUBLISHED);
460
				yearDescriptor.setValidator(new YearValidator());
461
				descriptors.addElement(yearDescriptor);
462
			}
463
		} 
464
				
465
		// URI
466
		if (id.equals(P_ID_URI)) {
467
			descriptors.addElement(
468
					isProtectedCache?
469
							new PropertyDescriptor(P_ID_URI, P_URI) :
470
							new TextPropertyDescriptor(P_ID_URI, P_URI));			
471
		} 
472
		
473
		// Title
474
		if (id.equals(P_ID_TITLE)) {
475
			descriptors.addElement(
476
					isProtectedCache?
477
							new PropertyDescriptor(P_ID_TITLE, P_TITLE) :
478
							new TextPropertyDescriptor(P_ID_TITLE, P_TITLE));			
479
		} 
480
		
481
		// In journal
482
		if (id.equals(P_ID_INJOURNAL)) {
483
			descriptors.addElement(
484
					isProtectedCache?
485
							new PropertyDescriptor(P_ID_INJOURNAL, P_INJOURNAL) :
486
							new TextPropertyDescriptor(P_ID_INJOURNAL, P_INJOURNAL));			
487
		}
488
		
489
		// Pages
490
		if (id.equals(P_ID_PAGES)) {
491
			descriptors.addElement(
492
					isProtectedCache?
493
							new PropertyDescriptor(P_ID_PAGES, P_PAGES) :
494
							new TextPropertyDescriptor(P_ID_PAGES, P_PAGES));			
495
		} 
496
		
497
		// Series
498
		if (id.equals(P_ID_SERIES)) {
499
			descriptors.addElement(
500
					isProtectedCache?
501
							new PropertyDescriptor(P_ID_SERIES, P_SERIES) :
502
							new TextPropertyDescriptor(P_ID_SERIES, P_SERIES));			
503
		} 
504
		
505
		// Volume
506
		if (id.equals(P_ID_VOLUME )) {
507
			descriptors.addElement(
508
					isProtectedCache?
509
							new PropertyDescriptor(P_ID_VOLUME, P_VOLUME) :
510
							new TextPropertyDescriptor(P_ID_VOLUME, P_VOLUME));			
511
		}
512
		
513
		// Editor
514
		if (id.equals(P_ID_EDITOR)) {
515
			descriptors.addElement(
516
					isProtectedCache?
517
							new PropertyDescriptor(P_ID_EDITOR, P_EDITOR) :
518
							new TextPropertyDescriptor(P_ID_EDITOR, P_EDITOR));			
519
		} 
520

    
521
		// Edition
522
		if (id.equals(P_ID_EDITION)) {
523
			descriptors.addElement(
524
					isProtectedCache?
525
							new PropertyDescriptor(P_ID_EDITION, P_EDITION) :
526
							new TextPropertyDescriptor(P_ID_EDITION, P_EDITION));			
527
		} 
528
		
529
		// Place published
530
		if (id.equals(P_ID_PLACEPUBLISHED)) {
531
			descriptors.addElement(
532
					isProtectedCache?
533
							new PropertyDescriptor(P_ID_PLACEPUBLISHED, P_PLACEPUBLISHED) :
534
							new TextPropertyDescriptor(P_ID_PLACEPUBLISHED, P_PLACEPUBLISHED));			
535
		}
536
		
537
		// Publisher
538
		if (id.equals(P_ID_PUBLISHER)) {
539
			descriptors.addElement(
540
					isProtectedCache?
541
							new PropertyDescriptor(P_ID_PUBLISHER, P_PUBLISHER) :
542
							new TextPropertyDescriptor(P_ID_PUBLISHER, P_PUBLISHER));			
543
		} 
544
		
545
		// ISSN
546
		if (id.equals(P_ID_ISSN)) {
547
			descriptors.addElement(
548
					isProtectedCache?
549
							new PropertyDescriptor(P_ID_ISSN, P_ISSN) :
550
							new TextPropertyDescriptor(P_ID_ISSN, P_ISSN));			
551
		} 
552
		
553
		// Institution
554
		if (id.equals(P_ID_INSTITUTION)) {
555
			descriptors.addElement(
556
					isProtectedCache?
557
							new PropertyDescriptor(P_ID_INSTITUTION, P_INSTITUTION) :
558
							new TextPropertyDescriptor(P_ID_INSTITUTION, P_INSTITUTION));			
559
		} 
560
		
561
		// School
562
		if (id.equals(P_ID_SCHOOL)) {
563
			descriptors.addElement(
564
					isProtectedCache?
565
							new PropertyDescriptor(P_ID_SCHOOL, P_SCHOOL) :
566
							new TextPropertyDescriptor(P_ID_SCHOOL, P_SCHOOL));			
567
		} 
568
		
569
		// In series
570
		if (id.equals(P_ID_INSERIES)) {
571
			descriptors.addElement(
572
					isProtectedCache?
573
							new PropertyDescriptor(P_ID_INSERIES, P_INSERIES) :
574
							new TextPropertyDescriptor(P_ID_INSERIES, P_INSERIES));			
575
		} 
576
		
577
		// Series part
578
		if (id.equals(P_ID_SERIESPART)) {
579
			descriptors.addElement(
580
					isProtectedCache?
581
							new PropertyDescriptor(P_ID_SERIESPART, P_SERIESPART) :
582
							new TextPropertyDescriptor(P_ID_SERIESPART, P_SERIESPART));			
583
		} 
584
		
585
		// ISBN
586
		if (id.equals(P_ID_ISBN)) {
587
			descriptors.addElement(
588
					isProtectedCache?
589
							new PropertyDescriptor(P_ID_ISBN, P_ISBN) :
590
							new TextPropertyDescriptor(P_ID_ISBN, P_ISBN));
591
		}
592
		
593
		// Organization
594
		if (id.equals(P_ID_ORGANIZATION)) {
595
			descriptors.addElement(
596
					isProtectedCache?
597
							new PropertyDescriptor(P_ID_ORGANIZATION, P_ORGANIZATION) :
598
							new TextPropertyDescriptor(P_ID_ORGANIZATION, P_ORGANIZATION));			
599
		} 
600
		
601
		// Printed unit
602
		if (id.equals(P_ID_PRINTEDUNIT)) {
603
			descriptors.addElement(
604
					isProtectedCache?
605
							new PropertyDescriptor(P_ID_PRINTEDUNIT, P_PRINTEDUNIT) :
606
							new TextPropertyDescriptor(P_ID_PRINTEDUNIT, P_PRINTEDUNIT));			
607
		} 
608
		
609
		// In book
610
		if (id.equals(P_ID_INBOOK)) {
611
			descriptors.addElement(
612
					isProtectedCache?
613
							new PropertyDescriptor(P_ID_INBOOK, P_INBOOK) :
614
							new TextPropertyDescriptor(P_ID_INBOOK, P_INBOOK));			
615
		}
616
		
617
		// Bibtex entry type
618
		if (id.equals(P_ID_BIBTEX_ENTRYTYPE)) {
619
			descriptors.addElement(
620
					isProtectedCache?
621
							new PropertyDescriptor(P_ID_BIBTEX_ENTRYTYPE, P_BIBTEX_ENTRYTYPE) :
622
							new ComboBoxPropertyDescriptor(P_ID_BIBTEX_ENTRYTYPE, P_BIBTEX_ENTRYTYPE, P_BIBTEX_ENTRYTYPE_MENU));			
623
		}
624
	}
625

    
626
	/**
627
	 * The default implementation of <code>ReferencePropertySource</code> will
628
	 * search all <code>ReferenceBase</code> classes.
629
	 * 
630
	 * @return
631
	 */
632
	protected int getSearchType() {
633
		return IReferenceSearch.BIBREF;
634
	}
635

    
636
	/**
637
	 * The default implementation of <code>ReferencePropertySource</code> will show
638
	 * a drop-down of reference types, but subclasses may want to show a non-editable
639
	 * text descriptor of the reference type. 
640
	 */
641
	protected PropertyDescriptor createReferenceTypeDescriptor() {
642
		return new ComboBoxPropertyDescriptor(
643
				P_ID_REFERENCETYPE, P_REFERENCETYPE, getReferenceTypeArray());
644
	}
645

    
646
	/* (non-Javadoc)
647
	 * @see org.eclipse.ui.views.properties.IPropertySource#getEditableValue()
648
	 */
649
	public Object getEditableValue() {
650
		return CdmUtils.Nz(reference.getTitleCache());
651
	}
652

    
653
	/* (non-Javadoc)
654
	 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyDescriptors()
655
	 */
656
	public IPropertyDescriptor[] getPropertyDescriptors() {
657
		return (IPropertyDescriptor[]) descriptors.toArray(
658
                new IPropertyDescriptor[descriptors.size()]);
659
	}
660

    
661
	/* (non-Javadoc)
662
	 * @see org.eclipse.ui.views.properties.IPropertySource#getPropertyValue(java.lang.Object)
663
	 */
664
	public Object getPropertyValue(Object id) {
665
				
666
		// Reference Type: get integer index of drop-down menu
667
		if (id.equals(P_ID_REFERENCETYPE)) {
668
			Class referenceClass = reference.getClass();
669
			int menuIndex = 0;
670
//			for (Class clazz : referenceTypeMap.keySet()) {
671
			for (Class clazz : getReferenceClassSet()) {
672
				if (clazz == referenceClass) {
673
					return menuIndex;
674
				}
675
				menuIndex++;
676
			}
677
			logger.warn("Reference class type " + referenceClass + " not in reference type menu.");
678
			return 0;
679
		}
680

    
681
		// Editable cache
682
		if (id.equals(P_ID_EDITABLECACHE)) {
683
			return (CdmUtils.Nz(reference.getTitleCache()));
684
		}
685
		
686
		// Protect cache?
687
		if (id.equals(P_ID_PROTECT_CACHE)) {
688
			if (reference.isProtectedTitleCache()) {
689
				return CACHE_PROTECTED;
690
			} else {
691
				return CACHE_NOT_PROTECTED;
692
			}
693
//			return reference.isProtectedTitleCache();
694
		}
695
		
696
		// Author Team: for now, just edit the cache
697
		// TODO AuthorTeamPropertySource
698
		if (id.equals(P_ID_AUTHORTEAM)) {
699
			TeamOrPersonBase authorTeam = reference.getAuthorTeam();
700
			
701
			if (authorTeam == null) {
702
				return "";
703
			}
704
			
705
			return CdmUtils.Nz(authorTeam.getTitleCache());
706
		}
707
		
708
		// Year
709
		if (id.equals(P_ID_YEAR)) {
710
			return CdmUtils.Nz(reference.getYear());
711
		}
712
		
713
		// URI
714
		if (id.equals(P_ID_URI)) {
715
			return CdmUtils.Nz(reference.getUri());
716
		}
717
		
718
		// Date published
719
		if (id.equals(P_ID_DATEPUBLISHED)) {
720
			TimePeriod datePublished = (TimePeriod) invokeMethod(reference, "getDatePublished", null);
721
			
722
			if (datePublished == null) {
723
				datePublished = TimePeriod.NewInstance();
724
			}
725
			
726
			if (reference.isProtectedTitleCache()) {
727
				return CdmUtils.Nz(reference.getYear());
728
			}
729
			
730
			TimePeriodPropertySource timePeriodPropertySource = 
731
					new TimePeriodPropertySource(datePublished);
732
			timePeriodPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
733
				public void propertyChange(PropertyChangeEvent evt) {
734
					if (reference instanceof StrictReferenceBase && evt.getNewValue() instanceof TimePeriod) {	
735
						((StrictReferenceBase) reference).setDatePublished((TimePeriod) evt.getNewValue());
736
					}
737
				}
738
			});
739
			return timePeriodPropertySource;
740
		}
741
		
742
		// Title: used by StrictReferenceBase
743
		if (id.equals(P_ID_TITLE)) {
744
			String title = (String) invokeMethod(reference, "getTitle", null);
745
			return CdmUtils.Nz(title);
746
		}
747
		
748
		// InJournal: return an instance of ReferencePropertySource
749
		if (id.equals(P_ID_INJOURNAL)) {
750
						
751
			Journal inJournal = (Journal) invokeMethod(reference, "getInJournal", null);
752
			
753
			if (inJournal == null) {
754
				inJournal = Journal.NewInstance();
755
			}
756
			
757
			if (reference.isProtectedTitleCache()) {
758
				return inJournal.getTitleCache(); 
759
			}
760
			
761
			ReferencePropertySource bibRefPropertySource = new SingleRefTypePropertySource(
762
					inJournal, SingleRefTypePropertySource.JOURNAL);
763
			bibRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
764
				public void propertyChange(PropertyChangeEvent evt) {
765
					if (reference instanceof Article && evt.getNewValue() instanceof Journal) {	
766
						((Article) reference).setInJournal((Journal) evt.getNewValue());
767
					}
768
				}
769
			});
770
			return bibRefPropertySource;
771
		}
772
		
773
		// Pages
774
		if (id.equals(P_ID_PAGES)) {
775
			String pages = (String) invokeMethod(reference, "getPages", null);
776
			return CdmUtils.Nz(pages);
777
		}
778
		
779
		// Series
780
		if (id.equals(P_ID_SERIES)) {
781
			String series = (String) invokeMethod(reference, "getSeries", null);
782
			return CdmUtils.Nz(series); 
783
		}
784

    
785
		// Volume
786
		if (id.equals(P_ID_VOLUME)) {
787
			String volume = (String) invokeMethod(reference, "getVolume", null);
788
			return CdmUtils.Nz(volume);			
789
		}
790

    
791
		// Editor
792
		if (id.equals(P_ID_EDITOR)) {
793
			String editor = (String) invokeMethod(reference, "getEditor", null);
794
			return CdmUtils.Nz(editor);			
795
		}
796

    
797
		// Edition
798
		if (id.equals(P_ID_EDITION)) {
799
			String edition = (String) invokeMethod(reference, "getEdition", null);
800
			return CdmUtils.Nz(edition);			
801
		}
802
		
803
		// Place published
804
		if (id.equals(P_ID_PLACEPUBLISHED)) {
805
			String placePublished = (String) invokeMethod(reference, "getPlacePublished", null);
806
			return CdmUtils.Nz(placePublished);
807
		}
808
		
809
		// Publisher
810
		if (id.equals(P_ID_PUBLISHER)) {
811
			String publisher = (String) invokeMethod(reference, "getPublisher", null);
812
			return CdmUtils.Nz(publisher);			
813
		}
814

    
815
		// ISSN
816
		if (id.equals(P_ID_ISSN)) {
817
			String issn = (String) invokeMethod(reference, "getIssn", null);
818
			return CdmUtils.Nz(issn);			
819
		}
820

    
821
		// Institution
822
		if (id.equals(P_ID_INSTITUTION)) {
823
			String institution = (String) invokeMethod(reference, "getInstitution", null);
824
			return CdmUtils.Nz(institution);			
825
		}
826

    
827
		// In series
828
		if (id.equals(P_ID_INSERIES)) {
829
			
830
		}
831
		
832
		// ISBN
833
		if (id.equals(P_ID_ISBN)) {
834
			String isbn = (String) invokeMethod(reference, "getIsbn", null);
835
			return CdmUtils.Nz(isbn);				
836
		}
837

    
838
		// Organization
839
		if (id.equals(P_ID_ORGANIZATION)) {
840
			String organization = (String) invokeMethod(reference, "getOrganization", null);
841
			return CdmUtils.Nz(organization);			
842
		}
843
		
844
		// In book
845
		if (id.equals(P_ID_INBOOK)) {
846
			
847
			Book inBook = (Book) invokeMethod(reference, "getInBook", null);
848
			
849
			if (inBook == null) {
850
				inBook = Book.NewInstance();
851
			}
852
			
853
			ReferencePropertySource bibRefPropertySource = new SingleRefTypePropertySource(
854
					inBook, SingleRefTypePropertySource.BOOK);
855
			bibRefPropertySource.addPropertyChangeListener(new PropertyChangeListener() {
856
				public void propertyChange(PropertyChangeEvent evt) {
857
					if (reference instanceof BookSection && evt.getNewValue() instanceof Book) {	
858
						((BookSection) reference).setInBook((Book) evt.getNewValue());
859
					}
860
				}
861
			});
862
			return bibRefPropertySource;
863
		}
864

    
865
		// Bibtex entry type
866
		if (id.equals(P_ID_BIBTEX_ENTRYTYPE)) {
867
			
868
		}
869
		
870
		return "";
871
	}
872

    
873
	/**
874
	 * Executes <code>methodName</code> on <code>obj</code> with
875
	 * the argument <code>arg</code>.
876
	 * <p>
877
	 * On failure, returns <code>null</code>.
878
	 * <p>
879
	 * NOTE:  both <code>Class.getMethod()</code> and <code>Method.invoke()</code>
880
	 * can be called with the <code>Object... args</code> approach, which allows
881
	 * the user to pass in a varying number of arguments. To keep it simple, and since
882
	 * this is usually only getters or setters, we are using only one argument.
883
	 * @param obj
884
	 * @param methodName
885
	 * @param args
886
	 * @return
887
	 */
888
	private Object invokeMethod(Object obj, String methodName, Object arg) {
889
		try {
890
			Method method = null;
891
			if (arg == null) {
892
				method = obj.getClass().getMethod(methodName);
893
				return method.invoke(obj);
894
			} else {
895
				method = obj.getClass().getMethod(methodName, arg.getClass());
896
				return method.invoke(obj, arg);
897
			}
898
		} catch (SecurityException e) {
899
			logger.error(e.getMessage());
900
		} catch (IllegalArgumentException e) {
901
			logger.error(e.getMessage());
902
		} catch (NoSuchMethodException e) {
903
			logger.error(e.getMessage());
904
		} catch (IllegalAccessException e) {
905
			logger.error(e.getMessage());
906
		} catch (InvocationTargetException e) {
907
			logger.error(e.getMessage());
908
		}
909
		return null;
910
	}
911

    
912
	/* (non-Javadoc)
913
	 * @see org.eclipse.ui.views.properties.IPropertySource#isPropertySet(java.lang.Object)
914
	 */
915
	public boolean isPropertySet(Object id) {
916
		return false;
917
	}
918

    
919
	/* (non-Javadoc)
920
	 * @see org.eclipse.ui.views.properties.IPropertySource#resetPropertyValue(java.lang.Object)
921
	 */
922
	public void resetPropertyValue(Object id) {}
923

    
924
	/* (non-Javadoc)
925
	 * @see org.eclipse.ui.views.properties.IPropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
926
	 */
927
	public void setPropertyValue(Object id, Object value) {
928
		
929
		// Search result
930
		if (id.equals(P_ID_SEARCH)) {
931
			if (value instanceof ReferenceBase) {
932
				reference = (ReferenceBase) value;
933
			}
934
		}
935

    
936
		// Protect cache? 
937
		if (id.equals(P_ID_PROTECT_CACHE)) {
938
			if (((Integer) value).intValue() == CACHE_PROTECTED) {
939
				reference.setProtectedTitleCache(true);
940
			} else {
941
				reference.setProtectedTitleCache(false);
942
			}
943
//			reference.setProtectedTitleCache(((Boolean) value).booleanValue());
944
		}
945
				
946
		// Reference Type
947
		if (id.equals(P_ID_REFERENCETYPE)) {
948
			
949
			// NOTE: this code will only be reached if user actually changes choice in reference type
950
			//	dropdown list, not if focus is merely gained and lost without changing the value
951
			
952
			// Grab reference's title cache
953
			String oldTitleCache = reference.getTitleCache();
954
			
955
			// Get reference's class
956
			int menuIndex;
957
			try {
958
				menuIndex = ((Integer) value).intValue();
959
			} catch (ClassCastException e) {
960
				// Leave method / no change on class cast error
961
				logger.error(e.getMessage());
962
				return;
963
			}			
964
			Class referenceClass = (Class)(getReferenceClassSet().toArray())[menuIndex];
965
			
966
			// Make a new reference using the class
967
			reference = makeNewReference(referenceClass);
968
			
969
			// Set new reference's title cache
970
			reference.setTitleCache(oldTitleCache);
971
		}
972
		
973
		// Author Team
974
		if (id.equals(P_ID_AUTHORTEAM)) {
975
			TeamOrPersonBase authorTeam = reference.getAuthorTeam();
976
			if (authorTeam == null) {
977
				authorTeam = Team.NewInstance();
978
				reference.setAuthorTeam(authorTeam);
979
			}
980
			try {
981
				authorTeam.setTitleCache((String) value);
982
			} catch (ClassCastException e) {
983
				// Leave method / no change on class cast error
984
				logger.error(e.getMessage());
985
				return;
986
			}
987
		}
988
		
989
		// Citation
990
		if (id.equals(P_ID_URI)) {
991
			String uri = (String) value;
992
			reference.setUri(uri);
993
		}
994
		
995
		// Year - only set directly by Bibtex refs
996
		if (id.equals(P_ID_YEAR)) {
997
			String year = (String) value;
998
			if (reference instanceof BibtexReference) {
999
				((BibtexReference) reference).setYear(year);
1000
			}
1001
		}
1002

    
1003
		// Title: used by StrictReferenceBase
1004
		if (id.equals(P_ID_TITLE)) {
1005
			String title = null;
1006
			try {
1007
				title = (String) value;
1008
			} catch (ClassCastException e) {
1009
				// Leave method / no change on class cast error
1010
				logger.error(e.getMessage());
1011
				return;
1012
			}
1013
			invokeMethod(reference, "setTitle", title);
1014
		}
1015

    
1016
		// Pages
1017
		if (id.equals(P_ID_PAGES)) {
1018
			invokeMethod(reference, "setPages", (String) value);
1019
		}
1020

    
1021
		// Series
1022
		if (id.equals(P_ID_SERIES)) {
1023
			invokeMethod(reference, "setSeries", (String) value);
1024
		}
1025
		
1026
		// Volume
1027
		if (id.equals(P_ID_VOLUME)) {
1028
			invokeMethod(reference, "setVolume", (String) value);
1029
		}
1030
		
1031
		// Editor
1032
		if (id.equals(P_ID_EDITOR)) {
1033
			invokeMethod(reference, "setEditor", (String) value);
1034
		}
1035

    
1036
		// Edition
1037
		if (id.equals(P_ID_EDITION)) {
1038
			invokeMethod(reference, "setEdition", (String) value);
1039
		}
1040
		
1041
		// Place published
1042
		if (id.equals(P_ID_PLACEPUBLISHED)) {
1043
			invokeMethod(reference, "setPlacePublished", (String) value);
1044
		}
1045

    
1046
		// Publisher
1047
		if (id.equals(P_ID_PUBLISHER)) {
1048
			invokeMethod(reference, "setPublisher", (String) value);
1049
		}
1050

    
1051
		// ISSN
1052
		if (id.equals(P_ID_ISSN)) {
1053
			invokeMethod(reference, "setIssn", (String) value);
1054
		}
1055

    
1056
		// Institution
1057
		if (id.equals(P_ID_INSTITUTION)) {
1058
			invokeMethod(reference, "setInstitution", (String) value);			
1059
		}
1060
		
1061
		// ISBN
1062
		if (id.equals(P_ID_ISBN)) {
1063
			invokeMethod(reference, "setIsbn", (String) value);
1064
		}
1065

    
1066
		// Organization
1067
		if (id.equals(P_ID_ORGANIZATION)) {
1068
			invokeMethod(reference, "setOrganization", (String) value);
1069
		}
1070

    
1071
		// In book
1072
		if (id.equals(P_ID_INBOOK)) {
1073
			Book inBook = (Book) invokeMethod(reference, "getInBook", null);
1074
			if (inBook == null) {
1075
				inBook = Book.NewInstance();
1076
				invokeMethod(reference, "setInBook", inBook);
1077
			}
1078
			inBook.setTitleCache((String) value);
1079
		}
1080
		
1081
		// Date published
1082
		if (id.equals(P_ID_DATEPUBLISHED)) {
1083
			
1084
			if (!(reference instanceof StrictReferenceBase)) {
1085
				return;
1086
			}
1087
			
1088
			if (value instanceof String) {
1089
				String year = (String) value;
1090
				TimePeriod yearsPublished = null;
1091
				
1092
				// If not empty, format is either "xxxx" or "xxxx-xxxx", thanks to validator
1093
				if (!year.equals("")) {
1094
					
1095
					// Convert to a TimePeriod
1096
					yearsPublished = TimeUtil.convertTimePeriod(year);
1097
					
1098
					// Update reference's dataPublished field
1099
					TimePeriod datePublished = ((StrictReferenceBase) reference).getDatePublished();
1100
					
1101
					if (datePublished == null) {
1102
						((StrictReferenceBase) reference).setDatePublished(yearsPublished);
1103
					} else {
1104
						
1105
						// Any months or days should be left as is - only update years 
1106
						datePublished.setStartYear(yearsPublished.getStartYear());
1107
						datePublished.setEndYear(yearsPublished.getEndYear());
1108
					}
1109
				} else {
1110
					((StrictReferenceBase) reference).setDatePublished(null);
1111
				}
1112
				
1113

    
1114
			}
1115
		}
1116

    
1117
		// Editable cache
1118
		if (id.equals(P_ID_EDITABLECACHE)) {
1119
			reference.setTitleCache((String) value);
1120
		} else {
1121
			reference.setTitleCache(reference.generateTitle(), reference.isProtectedTitleCache());
1122
		}
1123
		
1124
		propertyChangeSupport.firePropertyChange(Resources.PROPERTY_SHEET_CHANGE, null, reference);
1125
	}
1126
	
1127
	/**
1128
	 * Takes a <code>referenceClass</code>, then executes either its <code>NewInstance()</code> 
1129
	 * method or its constructor. Puts the resulting object in <code>this.reference</code> and
1130
	 * returns it.
1131
	 * <p>
1132
	 * If unsuccessful, <code>this.reference</code> keeps its old value and is returned.
1133
	 * @param referenceClass
1134
	 * @return
1135
	 */
1136
	private ReferenceBase makeNewReference(Class referenceClass) {
1137
				
1138
		// Check whether the class has a method "NewInstance()";
1139
		try {
1140
			Method method = referenceClass.getMethod("NewInstance", null);
1141
			reference = (ReferenceBase) method.invoke(null, null);
1142
		} catch (NoSuchMethodException e) {
1143
			try {
1144
				// If not, use its constructor
1145
				Constructor constructor = referenceClass.getConstructor(null);
1146
				reference = (ReferenceBase) constructor.newInstance(null);
1147
			} catch (SecurityException e1) {
1148
				e1.printStackTrace();
1149
			} catch (NoSuchMethodException e1) {
1150
				e1.printStackTrace();
1151
			} catch (IllegalArgumentException e1) {
1152
				e1.printStackTrace();
1153
			} catch (InstantiationException e1) {
1154
				e1.printStackTrace();
1155
			} catch (IllegalAccessException e1) {
1156
				e1.printStackTrace();
1157
			} catch (InvocationTargetException e1) {
1158
				e1.printStackTrace();
1159
			}
1160
		} catch (SecurityException e) {
1161
			e.printStackTrace();
1162
		} catch (IllegalArgumentException e) {
1163
			e.printStackTrace();
1164
		} catch (IllegalAccessException e) {
1165
			e.printStackTrace();
1166
		} catch (InvocationTargetException e) {
1167
			e.printStackTrace();
1168
		}
1169
		
1170
		return reference;
1171
	}
1172

    
1173
	public String toString() {
1174
		return CdmUtils.Nz(reference.getTitleCache());
1175
	}
1176

    
1177
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1178
	
1179
	public void addPropertyChangeListener(
1180
			PropertyChangeListener listener) {
1181
		propertyChangeSupport.addPropertyChangeListener(listener);
1182
	}
1183
}
(3-3/6)