diff -r 5cb74240a340 spi.viewmodel/apichanges.xml
--- a/spi.viewmodel/apichanges.xml Thu Sep 24 17:28:44 2009 +0200
+++ b/spi.viewmodel/apichanges.xml Fri Sep 25 00:16:40 2009 +0200
@@ -337,7 +337,21 @@
-
+
+
+ Introduction of AsynchronousModelFilter.
+
+
+
+
+
+ This API introduced AsynchronousModelFilter that
+ can be used by clients to override the default threading of their model implementations.
+
+
+
+
+
diff -r 5cb74240a340 spi.viewmodel/manifest.mf
--- a/spi.viewmodel/manifest.mf Thu Sep 24 17:28:44 2009 +0200
+++ b/spi.viewmodel/manifest.mf Fri Sep 25 00:16:40 2009 +0200
@@ -1,5 +1,5 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.spi.viewmodel/2
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/viewmodel/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.19
+OpenIDE-Module-Specification-Version: 1.20
diff -r 5cb74240a340 spi.viewmodel/src/org/netbeans/modules/viewmodel/AsynchronousModel.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/spi.viewmodel/src/org/netbeans/modules/viewmodel/AsynchronousModel.java Fri Sep 25 00:16:40 2009 +0200
@@ -0,0 +1,64 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ *
+ * The contents of this file are subject to the terms of either the GNU
+ * General Public License Version 2 only ("GPL") or the Common
+ * Development and Distribution License("CDDL") (collectively, the
+ * "License"). You may not use this file except in compliance with the
+ * License. You can obtain a copy of the License at
+ * http://www.netbeans.org/cddl-gplv2.html
+ * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
+ * specific language governing permissions and limitations under the
+ * License. When distributing the software, include this License Header
+ * Notice in each file and include the License file at
+ * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the GPL Version 2 section of the License file that
+ * accompanied this code. If applicable, add the following below the
+ * License Header, with the fields enclosed by brackets [] replaced by
+ * your own identifying information:
+ * "Portions Copyrighted [year] [name of copyright owner]"
+ *
+ * If you wish your version of this file to be governed by only the CDDL
+ * or only the GPL Version 2, indicate your decision by adding
+ * "[Contributor] elects to include this software in this distribution
+ * under the [CDDL or GPL Version 2] license." If you do not indicate a
+ * single choice of license, a recipient has the option to distribute
+ * your version of this file under either the CDDL, the GPL Version 2 or
+ * to extend the choice of license to its licensees as provided above.
+ * However, if you add GPL Version 2 code and therefore, elected the GPL
+ * Version 2 license, then the option applies only if the new code is
+ * made subject to such option by the copyright holder.
+ *
+ * Contributor(s):
+ *
+ * Portions Copyrighted 2009 Sun Microsystems, Inc.
+ */
+
+package org.netbeans.modules.viewmodel;
+
+import java.util.concurrent.Executor;
+import org.netbeans.spi.viewmodel.AsynchronousModelFilter.CALL;
+import org.netbeans.spi.viewmodel.UnknownTypeException;
+
+/**
+ * Not in public API, AsynchronousModelFilter is sufficient, since we have a default.
+ *
+ * @author Martin Entlicher
+ */
+public interface AsynchronousModel {
+
+ /**
+ * Provide the threading information for view models method calls.
+ * The returned Executor is used to call methods identified by
+ * {@link CALL} enum.
+ *
+ * @param asynchCall Identification of the method call
+ * @param node Object node
+ * @return an instance of Executor
+ */
+ Executor asynchronous(CALL asynchCall, Object node) throws UnknownTypeException;
+
+}
diff -r 5cb74240a340 spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelHyperNode.java
--- a/spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelHyperNode.java Thu Sep 24 17:28:44 2009 +0200
+++ b/spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelHyperNode.java Fri Sep 25 00:16:40 2009 +0200
@@ -43,12 +43,17 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
+
+import java.util.concurrent.Executor;
+import org.netbeans.spi.viewmodel.AsynchronousModelFilter;
+import org.netbeans.spi.viewmodel.AsynchronousModelFilter.CALL;
import org.netbeans.spi.viewmodel.Models;
import org.netbeans.spi.viewmodel.Models.TreeFeatures;
import org.netbeans.spi.viewmodel.TreeModelFilter;
import org.netbeans.spi.viewmodel.UnknownTypeException;
import org.openide.nodes.Children;
import org.openide.nodes.Node;
+import org.openide.util.Exceptions;
/**
*
@@ -112,7 +117,31 @@
super(null, model.getColumns(), treeModelRoot, object);
this.model = model;
}
-
+
+ // TODO: Run children of individual models according to individual asynchronous specifications
+ @Override
+ protected Executor getModelAsynchronous() {
+ Executor exec = null;
+ for (Models.CompoundModel m : model.getModels()) {
+ try {
+ Executor e = m.asynchronous(CALL.CHILDREN, object);
+ if (exec == null) {
+ exec = e;
+ } else {
+ if (e != AsynchronousModelFilter.CURRENT_THREAD) {
+ exec = e;
+ }
+ }
+ } catch (UnknownTypeException ex) {
+ Exceptions.printStackTrace(Exceptions.attachMessage(ex, "model = "+model+", object = "+object));
+ }
+ }
+ if (exec == null) {
+ exec = AsynchronousModelFilter.CURRENT_THREAD;
+ }
+ return exec;
+ }
+
@Override
protected Object[] getModelChildren(RefreshingInfo refreshInfo) throws UnknownTypeException {
if (refreshInfo instanceof HyperRefreshingInfo) {
diff -r 5cb74240a340 spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelNode.java
--- a/spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelNode.java Thu Sep 24 17:28:44 2009 +0200
+++ b/spi.viewmodel/src/org/netbeans/modules/viewmodel/TreeModelNode.java Fri Sep 25 00:16:40 2009 +0200
@@ -55,6 +55,7 @@
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
+import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
@@ -62,6 +63,8 @@
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
+import org.netbeans.spi.viewmodel.AsynchronousModelFilter;
+import org.netbeans.spi.viewmodel.AsynchronousModelFilter.CALL;
import org.netbeans.spi.viewmodel.ColumnModel;
import org.netbeans.spi.viewmodel.ModelEvent;
import org.netbeans.spi.viewmodel.Models;
@@ -106,6 +109,7 @@
private String shortDescription;
private final Object shortDescriptionLock = new Object();
private final Map properties = new HashMap();
+ private static final String EVALUATING_STR = NbBundle.getMessage(TreeModelNode.class, "EvaluatingProp");
// init ....................................................................
@@ -218,6 +222,27 @@
return shortDescription;
}
}
+ Executor exec;
+ try {
+ exec = model.asynchronous(CALL.SHORT_DESCRIPTION, object);
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(Exceptions.attachMessage(ex, "model = "+model+", object = "+object));
+ exec = AsynchronousModelFilter.CURRENT_THREAD;
+ }
+ if (exec == AsynchronousModelFilter.CURRENT_THREAD) {
+ return updateShortDescription();
+ } else {
+ exec.execute(new Runnable() {
+ public void run() {
+ updateShortDescription();
+ fireShortDescriptionChange(null, null);
+ }
+ });
+ return EVALUATING_STR;
+ }
+ }
+
+ private String updateShortDescription() {
try {
String sd = model.getShortDescription (object);
if (sd != null) {
@@ -404,17 +429,7 @@
boolean refreshed = false;
if ((ModelEvent.NodeChanged.DISPLAY_NAME_MASK & changeMask) != 0) {
try {
- String name = model.getDisplayName (object);
- if (name == null) {
- Throwable t =
- new NullPointerException (
- "Model: " + model + ".getDisplayName (" + object +
- ") = null!"
- );
- Exceptions.printStackTrace(t);
- } else {
- setName (name, false);
- }
+ setModelDisplayName();
} catch (UnknownTypeException e) {
Logger.getLogger(TreeModelNode.class.getName()).log(Level.CONFIG, "Model: "+model, e);
}
@@ -459,10 +474,10 @@
private static RequestProcessor requestProcessor;
// Accessed from test
RequestProcessor getRequestProcessor () {
- RequestProcessor rp = treeModelRoot.getRequestProcessor();
+ /*RequestProcessor rp = treeModelRoot.getRequestProcessor();
if (rp != null) {
return rp;
- }
+ }*/
synchronized (TreeModelNode.class) {
if (requestProcessor == null)
requestProcessor = new RequestProcessor ("TreeModel", 1);
@@ -498,19 +513,59 @@
}
}
}
+
+ private void setModelDisplayName() throws UnknownTypeException {
+ Executor exec;
+ try {
+ exec = model.asynchronous(CALL.DISPLAY_NAME, object);
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(Exceptions.attachMessage(ex, "model = "+model+", object = "+object));
+ exec = AsynchronousModelFilter.CURRENT_THREAD;
+ }
+ if (exec == AsynchronousModelFilter.CURRENT_THREAD) {
+ String name = model.getDisplayName (object);
+ if (name == null) {
+ Throwable t =
+ new NullPointerException (
+ "Model: " + model + ".getDisplayName (" + object +
+ ") = null!"
+ );
+ Exceptions.printStackTrace(t);
+ } else {
+ setName (name, false);
+ }
+ } else {
+ final String originalDisplayName = getDisplayName();
+ setName(EVALUATING_STR, false);
+ exec.execute(new Runnable() {
+ public void run() {
+ String name;
+ try {
+ name = model.getDisplayName(object);
+ } catch (UnknownTypeException ex) {
+ Logger.getLogger(TreeModelNode.class.getName()).log(Level.CONFIG, "Model: "+model, ex);
+ setName(originalDisplayName, false);
+ return ;
+ }
+ if (name == null) {
+ Throwable t =
+ new NullPointerException (
+ "Model: " + model + ".getDisplayName (" + object +
+ ") = null!"
+ );
+ Exceptions.printStackTrace(t);
+ setName(originalDisplayName, false);
+ } else {
+ setName (name, false);
+ }
+ }
+ });
+ }
+ }
private void refreshNode () {
try {
- String name = model.getDisplayName (object);
- if (name == null) {
- Throwable t =
- new NullPointerException (
- "Model: " + model + ".getDisplayName (" + object +
- ") = null!"
- );
- Exceptions.printStackTrace(t);
- }
- setName (name, false);
+ setModelDisplayName();
String iconBase = null;
if (model.getRoot() != object) {
iconBase = model.getIconBaseWithExtension (object);
@@ -834,7 +889,7 @@
/** Special locals subnodes (children) */
static class TreeModelChildren extends Children.Keys