001: /**
002: * <copyright>
003: * </copyright>
004: *
005: * $Id: BlackboardImpl.java 25826 2007-06-13 15:40:34Z vitalus $
006: */package net.refractions.udig.project.internal.impl;
007:
008: import java.io.BufferedInputStream;
009: import java.io.BufferedOutputStream;
010: import java.io.ByteArrayInputStream;
011: import java.io.ByteArrayOutputStream;
012: import java.io.ObjectInputStream;
013: import java.io.ObjectOutputStream;
014: import java.io.Serializable;
015: import java.io.StringReader;
016: import java.io.StringWriter;
017: import java.util.ArrayList;
018: import java.util.Collection;
019: import java.util.Collections;
020: import java.util.Comparator;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.concurrent.CopyOnWriteArraySet;
024:
025: import net.refractions.udig.core.internal.ExtensionPointProcessor;
026: import net.refractions.udig.core.internal.ExtensionPointUtil;
027: import net.refractions.udig.project.BlackboardEvent;
028: import net.refractions.udig.project.IBlackboardListener;
029: import net.refractions.udig.project.IPersister;
030: import net.refractions.udig.project.IProvider;
031: import net.refractions.udig.project.internal.Blackboard;
032: import net.refractions.udig.project.internal.BlackboardEntry;
033: import net.refractions.udig.project.internal.ProjectPackage;
034: import net.refractions.udig.project.internal.ProjectPlugin;
035:
036: import org.eclipse.core.runtime.IConfigurationElement;
037: import org.eclipse.core.runtime.IExtension;
038: import org.eclipse.core.runtime.IStatus;
039: import org.eclipse.core.runtime.Status;
040: import org.eclipse.emf.common.notify.NotificationChain;
041: import org.eclipse.emf.common.util.EList;
042: import org.eclipse.emf.ecore.EClass;
043: import org.eclipse.emf.ecore.EStructuralFeature;
044: import org.eclipse.emf.ecore.InternalEObject;
045: import org.eclipse.emf.ecore.impl.EObjectImpl;
046: import org.eclipse.emf.ecore.util.EObjectContainmentEList;
047: import org.eclipse.emf.ecore.util.InternalEList;
048: import org.eclipse.ui.XMLMemento;
049:
050: /**
051: *
052: * @author Jesse
053: * @since 1.0.0
054: * @generated
055: */
056: public class BlackboardImpl extends EObjectImpl implements Blackboard {
057:
058: // MutablePicoContainer picoContainer = new DefaultPicoContainer();
059: /**
060: * underlying container *
061: *
062: * @uml.property name="blackboard"
063: * @uml.associationEnd qualifier="key:java.lang.Object
064: * net.refractions.udig.project.internal.impl.BlackboardEntryImpl"
065: */
066: HashMap<String, BlackboardEntry> blackboard = new HashMap<String, BlackboardEntry>();
067:
068: /** persisters * */
069: ArrayList<IPersister<Object>> persisters;
070: /** providers * */
071: ArrayList<IProvider<Object>> providers;
072:
073: boolean initialized = false;
074:
075: /**
076: * <!-- begin-user-doc --> <!-- end-user-doc -->
077: * @generated
078: */
079: public static final String copyright = "uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004, Refractions Research Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details."; //$NON-NLS-1$
080:
081: /**
082: * The cached value of the '{@link #getEntries() <em>Entries</em>}' containment reference list.
083: * <!-- begin-user-doc --> <!-- end-user-doc -->
084: * @see #getEntries()
085: * @generated
086: * @ordered
087: */
088: protected EList entries = null;
089:
090: /**
091: * <!-- begin-user-doc --> <!-- end-user-doc -->
092: * @generated
093: */
094: protected BlackboardImpl() {
095: super ();
096: }
097:
098: /**
099: * <!-- begin-user-doc --> <!-- end-user-doc -->
100: * @generated
101: */
102: protected EClass eStaticClass() {
103: return ProjectPackage.eINSTANCE.getBlackboard();
104: }
105:
106: /**
107: * <!-- begin-user-doc --> <!-- end-user-doc -->
108: * @generated
109: */
110: @SuppressWarnings("unchecked")
111: public List<BlackboardEntry> getEntries() {
112: if (entries == null) {
113: entries = new EObjectContainmentEList(
114: BlackboardEntry.class, this ,
115: ProjectPackage.BLACKBOARD__ENTRIES);
116: }
117: return entries;
118: }
119:
120: /**
121: * <!-- begin-user-doc --> <!-- end-user-doc -->
122: * @generated
123: */
124: @SuppressWarnings("unchecked")
125: public NotificationChain eInverseRemove(InternalEObject otherEnd,
126: int featureID, Class baseClass, NotificationChain msgs) {
127: if (featureID >= 0) {
128: switch (eDerivedStructuralFeatureID(featureID, baseClass)) {
129: case ProjectPackage.BLACKBOARD__ENTRIES:
130: return ((InternalEList) getEntries()).basicRemove(
131: otherEnd, msgs);
132: default:
133: return eDynamicInverseRemove(otherEnd, featureID,
134: baseClass, msgs);
135: }
136: }
137: return eBasicSetContainer(null, featureID, msgs);
138: }
139:
140: /**
141: * <!-- begin-user-doc --> <!-- end-user-doc -->
142: * @generated
143: */
144: public Object eGet(EStructuralFeature eFeature, boolean resolve) {
145: switch (eDerivedStructuralFeatureID(eFeature)) {
146: case ProjectPackage.BLACKBOARD__ENTRIES:
147: return getEntries();
148: }
149: return eDynamicGet(eFeature, resolve);
150: }
151:
152: /**
153: * <!-- begin-user-doc --> <!-- end-user-doc -->
154: * @generated
155: */
156: @SuppressWarnings("unchecked")//$NON-NLS-1$
157: public void eSet(EStructuralFeature eFeature, Object newValue) {
158: switch (eDerivedStructuralFeatureID(eFeature)) {
159: case ProjectPackage.BLACKBOARD__ENTRIES:
160: getEntries().clear();
161: getEntries().addAll((Collection) newValue);
162: return;
163: }
164: eDynamicSet(eFeature, newValue);
165: }
166:
167: /**
168: * <!-- begin-user-doc --> <!-- end-user-doc -->
169: * @generated
170: */
171: public void eUnset(EStructuralFeature eFeature) {
172: switch (eDerivedStructuralFeatureID(eFeature)) {
173: case ProjectPackage.BLACKBOARD__ENTRIES:
174: getEntries().clear();
175: return;
176: }
177: eDynamicUnset(eFeature);
178: }
179:
180: /**
181: * <!-- begin-user-doc --> <!-- end-user-doc -->
182: * @generated
183: */
184: public boolean eIsSet(EStructuralFeature eFeature) {
185: switch (eDerivedStructuralFeatureID(eFeature)) {
186: case ProjectPackage.BLACKBOARD__ENTRIES:
187: return entries != null && !entries.isEmpty();
188: }
189: return eDynamicIsSet(eFeature);
190: }
191:
192: /*
193: * (non-Javadoc)
194: *
195: * @see net.refractions.udig.project.IBlackboard#contains(java.lang.String)
196: */
197: public boolean contains(String key) {
198: return get(key) != null;
199: }
200:
201: /*
202: * (non-Javadoc)
203: *
204: * @see net.refractions.udig.project.IBlackboard#get(java.lang.String)
205: */
206: @SuppressWarnings("unchecked")//$NON-NLS-1$
207: public Object get(String key) {
208: if (!initialized) {
209: initialize();
210: }
211: if (key == null)
212: return null;
213:
214: // look up the entry
215: BlackboardEntry entry = blackboard.get(key);
216: if (entry != null) {
217:
218: if (entry.getObject() != null) {
219: return entry.getObject();
220: } else {
221: Object object = null;
222: try {
223: // have to load from memento
224: String memento2 = entry.getMemento();
225: if (memento2 == null || memento2.length() == 0)
226: return null;
227: XMLMemento memento = XMLMemento
228: .createReadRoot(new StringReader(memento2));
229: IPersister persister = findPersister(entry, memento);
230: if (persister != null) {
231: object = persister.load(memento);
232: entry.setObject(object);
233: entry.setObjectClass(object.getClass());
234: } else {
235: // try serializability
236: if (entry.getObjectClass() != null
237: && entry.getObjectClass()
238: .isAssignableFrom(
239: Serializable.class)) {
240: ByteArrayInputStream bin = new ByteArrayInputStream(
241: memento2.getBytes());
242: ObjectInputStream in = new ObjectInputStream(
243: new BufferedInputStream(bin));
244: object = in.readObject();
245: in.close();
246:
247: entry.setObject(object);
248: entry.setObjectClass(object.getClass());
249: } else {
250: // either object not serializable, or type can not
251: // derminated
252: }
253:
254: }
255: } catch (Exception e) {
256: String msg = "Error loading content: " + entry.getObjectClass(); //$NON-NLS-1$
257: IStatus status = new Status(IStatus.WARNING,
258: "", 0, msg, e); //$NON-NLS-1$
259: ProjectPlugin.getPlugin().getLog().log(status);
260: }
261:
262: return object;
263: }
264: } else {
265: // object does not exists, try to find a provider
266: IProvider provider = findProvider(key);
267: if (provider != null) {
268: try {
269: Object object = provider.provide();
270: if (object != null) {
271: createEntry(key, object);
272: return object;
273: }
274: } catch (Exception e) {
275: String msg = "provider exception :" + key; //$NON-NLS-1$
276: String id = provider.getExtension().getNamespace();
277: IStatus status = new Status(IStatus.WARNING, id, 0,
278: msg, e);
279:
280: ProjectPlugin.getPlugin().getLog().log(status);
281: }
282: }
283: }
284:
285: return null;
286: }
287:
288: private void initialize() {
289: initialized = true;
290: for (BlackboardEntry entry : this .getEntries()) {
291: blackboard.put(entry.getKey(), entry);
292: }
293: }
294:
295: /*
296: * (non-Javadoc)
297: *
298: * @see net.refractions.udig.project.IBlackboard#put(java.lang.String, java.lang.Object)
299: */
300: public void put(String key, Object value) {
301: if (key == null)
302: return;
303:
304: // look up the entry
305: BlackboardEntry entry = blackboard.get(key);
306: if (entry == null) {
307: entry = createEntry(key, value);
308: }
309:
310: Object oldValue = entry.getObject();
311:
312: // set the cache
313: entry.setObject(value);
314:
315: // find the persister to save the state
316: IPersister<Object> persister = findPersister(entry, null);
317: try {
318: if (persister != null) {
319: XMLMemento memento = XMLMemento
320: .createWriteRoot("blackboardContent"); //$NON-NLS-1$
321: persister.save(value, memento);
322: memento
323: .putString(
324: "internalObjectClassStorage", entry.getObjectClass().getName()); //$NON-NLS-1$
325:
326: StringWriter writer = new StringWriter();
327: memento.save(writer);
328: entry.setMemento(writer.getBuffer().toString());
329: } else {
330: // no persister, try using serializability
331: if (value instanceof Serializable) {
332: ByteArrayOutputStream bout = new ByteArrayOutputStream();
333:
334: ObjectOutputStream out = new ObjectOutputStream(
335: new BufferedOutputStream(bout));
336: out.writeObject(value);
337:
338: entry.setMemento(new String(bout.toByteArray()));
339: out.close();
340: }
341: }
342: } catch (Exception e) {
343: String msg = "Error persisting content: " + value.getClass(); //$NON-NLS-1$
344: if (persister != null) {
345: IExtension ext = persister.getExtension();
346: IStatus status = new Status(IStatus.WARNING, ext
347: .getNamespaceIdentifier(), 0, msg, e);
348: ProjectPlugin.getPlugin().getLog().log(status);
349: } else {
350: ProjectPlugin.log("error loading persister", e); //$NON-NLS-1$
351: }
352: }
353: BlackboardEvent event = new BlackboardEvent(this , key,
354: oldValue, value);
355: for (IBlackboardListener l : listeners) {
356: try {
357: l.blackBoardChanged(event);
358: } catch (Exception e) {
359: ProjectPlugin.log("", e); //$NON-NLS-1$
360: }
361: }
362: }
363:
364: /*
365: * (non-Javadoc)
366: *
367: * @see net.refractions.udig.project.IBlackboard#getFloat(java.lang.String)
368: */
369: public Float getFloat(String key) {
370: Object o = get(key);
371: if (o != null && o instanceof Float) {
372: return (Float) o;
373: }
374:
375: return null;
376: }
377:
378: /*
379: * (non-Javadoc)
380: *
381: * @see net.refractions.udig.project.IBlackboard#getInteger(java.lang.String)
382: */
383: public Integer getInteger(String key) {
384: Object o = get(key);
385: if (o != null && o instanceof Integer) {
386: return (Integer) o;
387: }
388:
389: return null;
390: }
391:
392: /*
393: * (non-Javadoc)
394: *
395: * @see net.refractions.udig.project.IBlackboard#getString(java.lang.String)
396: */
397: public String getString(String key) {
398: Object o = get(key);
399: if (o != null && o instanceof String) {
400: return (String) o;
401: }
402:
403: return null;
404: }
405:
406: /*
407: * (non-Javadoc)
408: *
409: * @see net.refractions.udig.project.IBlackboard#putFloat(java.lang.String, float)
410: */
411: public void putFloat(String key, float value) {
412: put(key, value);
413: }
414:
415: /*
416: * (non-Javadoc)
417: *
418: * @see net.refractions.udig.project.IBlackboard#putInteger(java.lang.String, int)
419: */
420: public void putInteger(String key, int value) {
421: put(key, value);
422:
423: }
424:
425: /*
426: * (non-Javadoc)
427: *
428: * @see net.refractions.udig.project.IBlackboard#putString(java.lang.String, java.lang.String)
429: */
430: public void putString(String key, String value) {
431: put(key, value);
432: }
433:
434: /*
435: * (non-Javadoc)
436: *
437: * @see net.refractions.udig.project.IBlackboard#clear()
438: */
439: public void clear() {
440: blackboard.clear();
441: for (IBlackboardListener l : listeners) {
442: l.blackBoardCleared(this );
443: }
444: }
445:
446: CopyOnWriteArraySet<IBlackboardListener> listeners = new CopyOnWriteArraySet<IBlackboardListener>();
447:
448: public boolean addListener(IBlackboardListener listener) {
449: return listeners.add(listener);
450: }
451:
452: public boolean removeListener(IBlackboardListener listener) {
453: return listeners.remove(listener);
454: }
455:
456: /**
457: * Flushes all the cached objects. Useful for testing.
458: */
459: public void flush() {
460: for (BlackboardEntry entry : blackboard.values()) {
461: entry.setObject(null);
462: }
463: }
464:
465: private IProvider findProvider(String key) {
466: if (providers == null) {
467: providers = new ArrayList<IProvider<Object>>();
468: ProviderProcessor p = new ProviderProcessor(providers);
469: ExtensionPointUtil.process(ProjectPlugin.getPlugin(),
470: IProvider.XPID, p);
471: }
472:
473: // search for provider matching key
474: for (IProvider<Object> provider : providers) {
475: if (provider.getKey() != null
476: && provider.getKey().equals(key))
477: return provider;
478: }
479:
480: return null;
481: }
482:
483: @SuppressWarnings("unchecked")
484: private BlackboardEntryImpl createEntry(String key, Object object) {
485:
486: BlackboardEntryImpl entry = new BlackboardEntryImpl();
487:
488: entry.setKey(key);
489: entry.setObjectClass(object != null ? object.getClass() : null);
490: blackboard.put(key, entry);
491:
492: // add to entries for persistance
493: getEntries().add(entry);
494:
495: return entry;
496: }
497:
498: @SuppressWarnings("unchecked")
499: private IPersister<Object> findPersister(BlackboardEntry entry,
500: XMLMemento memento) {
501:
502: if (persisters == null) {
503: synchronized (this ) {
504: if (persisters == null) {
505: persisters = new ArrayList<IPersister<Object>>();
506: PersisterProcessor p = new PersisterProcessor(
507: persisters);
508: ExtensionPointUtil.process(ProjectPlugin
509: .getPlugin(), IPersister.XPID, p);
510: }
511: }
512: }
513:
514: // look for a class closest down in the class hierarchy
515: ArrayList<IPersister<Object>> possible = new ArrayList<IPersister<Object>>();
516:
517: for (IPersister<Object> persister : persisters) {
518: Class persistee = persister.getPersistee();
519: if (persistee == null)
520: continue;
521:
522: Class objectClass = entry.getObjectClass();
523: if (objectClass == null && memento != null) {
524: try {
525: objectClass = persister
526: .getClass()
527: .getClassLoader()
528: .loadClass(
529: memento
530: .getString("internalObjectClassStorage")); //$NON-NLS-1$
531: } catch (Exception e) {
532: ProjectPlugin.log("", e); //$NON-NLS-1$
533: continue;
534: }
535: }
536: if (objectClass != null
537: && objectClass.isAssignableFrom(persistee)) {
538: possible.add(persister);
539: }
540: }
541: if (possible.isEmpty())
542: return null;
543:
544: Collections.sort(possible,
545: new Comparator<IPersister<Object>>() {
546: public int compare(IPersister<Object> p1,
547: IPersister<Object> p2) {
548: if (p1.getPersistee().equals(p2.getPersistee()))
549: return 0;
550: if (p1.getPersistee().isAssignableFrom(
551: p2.getPersistee()))
552: return -1;
553:
554: return 1;
555: }
556: });
557:
558: return possible.get(0);
559: }
560:
561: static class ProviderProcessor implements ExtensionPointProcessor {
562:
563: List<IProvider<Object>> providers;
564:
565: ProviderProcessor(List<IProvider<Object>> providers) {
566: this .providers = providers;
567: }
568:
569: @SuppressWarnings("unchecked")
570: public void process(IExtension extension,
571: IConfigurationElement element) throws Exception {
572: try {
573: IProvider<Object> provider = (IProvider<Object>) element
574: .createExecutableExtension("class"); //$NON-NLS-1$
575:
576: if (provider != null) {
577: providers.add(provider);
578: provider.setExtension(extension);
579: if (element.getAttribute("key") != null) { //$NON-NLS-1$
580: provider.setKey(element.getAttribute("key")); //$NON-NLS-1$
581: }
582: }
583: } catch (Throwable t) {
584: ProjectPlugin.log(t.getLocalizedMessage(), t);
585: }
586: }
587: }
588:
589: static class PersisterProcessor implements ExtensionPointProcessor {
590:
591: List persisters;
592:
593: PersisterProcessor(List persisters) {
594: this .persisters = persisters;
595: }
596:
597: @SuppressWarnings("unchecked")
598: public void process(IExtension extension,
599: IConfigurationElement element) throws Exception {
600:
601: try {
602: IPersister persister = (IPersister) element
603: .createExecutableExtension("class"); //$NON-NLS-1$
604:
605: if (persister != null) {
606: persister.setExtension(extension);
607: persisters.add(persister);
608: }
609: } catch (Throwable t) {
610: ProjectPlugin.log(t.getLocalizedMessage(), t);
611: }
612:
613: }
614: }
615: } // BlackboardImpl
|