001: package net.refractions.udig.project.internal.provider;
002:
003: import java.util.Collection;
004: import java.util.Iterator;
005: import java.util.List;
006:
007: import net.refractions.udig.project.edit.internal.Messages;
008:
009: import org.eclipse.emf.common.notify.AdapterFactory;
010: import org.eclipse.emf.ecore.EObject;
011: import org.eclipse.emf.ecore.EStructuralFeature;
012: import org.eclipse.emf.edit.provider.ItemProviderAdapter;
013: import org.eclipse.swt.SWTException;
014: import org.eclipse.swt.graphics.Image;
015: import org.eclipse.swt.widgets.Display;
016:
017: public class AbstractLazyLoadingItemProvider extends
018: ItemProviderAdapter {
019:
020: protected volatile ChildFetcher childFetcher;
021:
022: /**
023: * Gets the "real" list of children so that the children in childFetcher doesn't have to be kept in sync with
024: * the real data...
025: *
026: * @param object object that is the parent.
027: * @return
028: */
029: @SuppressWarnings("unchecked")
030: protected Collection<? extends Object> getConcreteChildren(
031: Object object) {
032: return super .getChildren(object);
033: }
034:
035: /**
036: * Returns the child at the indicated index or null if there is fewer children
037: *
038: * @param object the parent object.
039: * @param childIndex the index of the child to return.
040: * @return the child at the indicated index or null if there is fewer children
041: */
042: @SuppressWarnings("unchecked")
043: public Object getChild(Object object, int childIndex) {
044: if (!(object instanceof EObject))
045: return null;
046: int currentIndex = 0;
047: Collection<EStructuralFeature> features = getChildrenFeatures(object);
048: for (EStructuralFeature feature : features) {
049: Object value = getFeatureValue((EObject) object, feature);
050: if (value instanceof Collection) {
051: Collection<Object> collection = (Collection) value;
052:
053: // index of child is in another feature
054: if (currentIndex + collection.size() < childIndex)
055: continue;
056: // ok the child is in this feature lets find it.
057: if (value instanceof List) {
058: List list = ((List) value);
059: if (currentIndex + list.size() <= childIndex) {
060: currentIndex += list.size();
061: continue;
062: }
063: return list.get(childIndex);
064: } else {
065: Iterator<Object> iter = collection.iterator();
066: while (currentIndex < childIndex) {
067: iter.next();
068: currentIndex++;
069: }
070: return iter.next();
071: }
072: }
073: currentIndex++;
074: if (currentIndex == childIndex)
075: return value;
076: }
077: return null;
078: }
079:
080: @Override
081: public Collection getElements(Object arg0) {
082: return getChildren(arg0);
083: }
084:
085: @SuppressWarnings("unchecked")
086: @Override
087: public Collection getChildren(Object object) {
088: if (Display.getCurrent() == null)
089: throw new SWTException(
090: "Invalid Thread access, not in UI thread."); //$NON-NLS-1$
091:
092: if (!getChildFetcher().dataReady) {
093: getChildFetcher().parent = object;
094: getChildFetcher().schedule();
095: return getChildFetcher().getChildren();
096: }
097:
098: return getConcreteChildren(object);
099: }
100:
101: public ChildFetcher getChildFetcher() {
102: if (childFetcher == null) {
103: synchronized (this ) {
104: if (childFetcher == null) {
105: childFetcher = createChildFetcher();
106: }
107: }
108: }
109:
110: return childFetcher;
111: }
112:
113: private static final LoadingPlaceHolder LOADING_PLACEHOLDER = new LoadingPlaceHolder() {
114:
115: public Image getImage() {
116: return null;
117: }
118:
119: public String getText() {
120: return Messages.ProjectItemProvider_loading;
121: }
122:
123: @Override
124: public String toString() {
125: return getText();
126: }
127:
128: };
129:
130: /**
131: * Returns a placeholder item. It should be a stateless object and a singleton.
132: *
133: * @return a placeholder item. It should be a stateless object and a singleton.
134: */
135: protected LoadingPlaceHolder getLoadingItem() {
136: return LOADING_PLACEHOLDER;
137: }
138:
139: /**
140: * Creates a new instance of a {@link ChildFetcher}. Does not retrieve an old instance.
141: *
142: * @return new instance of a {@link ChildFetcher}
143: */
144: protected ChildFetcher createChildFetcher() {
145: return new ChildFetcher(this );
146: }
147:
148: public AbstractLazyLoadingItemProvider(AdapterFactory adapterFactory) {
149: super(adapterFactory);
150: }
151:
152: }
|