Source Code Cross Referenced for TreeModelNode.java in  » IDE-Netbeans » spi » org » netbeans » modules » viewmodel » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » spi » org.netbeans.modules.viewmodel 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003:         *
0004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * The contents of this file are subject to the terms of either the GNU
0007:         * General Public License Version 2 only ("GPL") or the Common
0008:         * Development and Distribution License("CDDL") (collectively, the
0009:         * "License"). You may not use this file except in compliance with the
0010:         * License. You can obtain a copy of the License at
0011:         * http://www.netbeans.org/cddl-gplv2.html
0012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013:         * specific language governing permissions and limitations under the
0014:         * License.  When distributing the software, include this License Header
0015:         * Notice in each file and include the License file at
0016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
0017:         * particular file as subject to the "Classpath" exception as provided
0018:         * by Sun in the GPL Version 2 section of the License file that
0019:         * accompanied this code. If applicable, add the following below the
0020:         * License Header, with the fields enclosed by brackets [] replaced by
0021:         * your own identifying information:
0022:         * "Portions Copyrighted [year] [name of copyright owner]"
0023:         *
0024:         * Contributor(s):
0025:         *
0026:         * The Original Software is NetBeans. The Initial Developer of the Original
0027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028:         * Microsystems, Inc. All Rights Reserved.
0029:         *
0030:         * If you wish your version of this file to be governed by only the CDDL
0031:         * or only the GPL Version 2, indicate your decision by adding
0032:         * "[Contributor] elects to include this software in this distribution
0033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034:         * single choice of license, a recipient has the option to distribute
0035:         * your version of this file under either the CDDL, the GPL Version 2 or
0036:         * to extend the choice of license to its licensees as provided above.
0037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
0038:         * Version 2 license, then the option applies only if the new code is
0039:         * made subject to such option by the copyright holder.
0040:         */
0041:
0042:        package org.netbeans.modules.viewmodel;
0043:
0044:        import java.awt.datatransfer.Transferable;
0045:        import java.awt.event.ActionEvent;
0046:        import java.awt.event.KeyEvent;
0047:        import java.beans.PropertyEditor;
0048:        import java.lang.IllegalAccessException;
0049:        import java.lang.ref.WeakReference;
0050:        import java.io.IOException;
0051:        import java.util.ArrayList;
0052:        import java.util.Arrays;
0053:        import java.util.Collections;
0054:        import java.util.HashMap;
0055:        import java.util.Iterator;
0056:        import java.util.LinkedList;
0057:        import java.util.List;
0058:        import java.util.Map;
0059:        import java.util.WeakHashMap;
0060:        import javax.swing.AbstractAction;
0061:        import javax.swing.Action;
0062:        import javax.swing.KeyStroke;
0063:        import javax.swing.SwingUtilities;
0064:
0065:        import org.netbeans.spi.viewmodel.ColumnModel;
0066:        import org.netbeans.spi.viewmodel.ModelEvent;
0067:        import org.netbeans.spi.viewmodel.Models;
0068:        import org.netbeans.spi.viewmodel.TreeModel;
0069:        import org.netbeans.spi.viewmodel.UnknownTypeException;
0070:        import org.openide.ErrorManager;
0071:
0072:        import org.openide.nodes.AbstractNode;
0073:        import org.openide.nodes.Children;
0074:        import org.openide.nodes.Node;
0075:        import org.openide.nodes.PropertySupport;
0076:        import org.openide.nodes.Sheet;
0077:        import org.openide.util.NbBundle;
0078:        import org.openide.util.RequestProcessor;
0079:        import org.openide.util.RequestProcessor.Task;
0080:        import org.openide.util.datatransfer.PasteType;
0081:        import org.openide.util.lookup.Lookups;
0082:
0083:        /**
0084:         *
0085:         * @author   Jan Jancura
0086:         */
0087:        public class TreeModelNode extends AbstractNode {
0088:
0089:            /**
0090:             * The maximum length of text that is interpreted as HTML.
0091:             * This is documented at openide/explorer/src/org/openide/explorer/doc-files/propertyViewCustomization.html
0092:             */
0093:            private static final int MAX_HTML_LENGTH = 511;
0094:
0095:            // variables ...............................................................
0096:
0097:            private Models.CompoundModel model;
0098:            private TreeModelRoot treeModelRoot;
0099:            private Object object;
0100:
0101:            private String htmlDisplayName;
0102:            private Map<String, Object> properties = new HashMap<String, Object>();
0103:
0104:            // init ....................................................................
0105:
0106:            /**
0107:             * Creates root of call stack for given producer.
0108:             */
0109:            public TreeModelNode(final Models.CompoundModel model,
0110:                    final TreeModelRoot treeModelRoot, final Object object) {
0111:                super (createChildren(model, treeModelRoot, object), Lookups
0112:                        .singleton(object));
0113:                this .model = model;
0114:                this .treeModelRoot = treeModelRoot;
0115:                this .object = object;
0116:
0117:                // <RAVE>
0118:                // Use the modified CompoundModel class's field to set the 
0119:                // propertiesHelpID for properties sheets if the model's helpID
0120:                // has been set
0121:                if (model.getHelpId() != null) {
0122:                    this .setValue("propertiesHelpID", model.getHelpId()); // NOI18N
0123:                }
0124:                // </RAVE>
0125:
0126:                treeModelRoot.registerNode(object, this );
0127:                refreshNode();
0128:                initProperties();
0129:            }
0130:
0131:            // Node implementation .....................................................
0132:
0133:            private void initProperties() {
0134:                Sheet sheet = Sheet.createDefault();
0135:                Sheet.Set ps = Sheet.createPropertiesSet();
0136:                ColumnModel[] columns = model.getColumns();
0137:                int i, k = columns.length;
0138:                for (i = 0; i < k; i++)
0139:                    ps.put(new MyProperty(columns[i], treeModelRoot));
0140:                sheet.put(ps);
0141:                setSheet(sheet);
0142:            }
0143:
0144:            private static Children createChildren(Models.CompoundModel model,
0145:                    TreeModelRoot treeModelRoot, Object object) {
0146:                if (object == null)
0147:                    throw new NullPointerException();
0148:                try {
0149:                    return model.isLeaf(object) ? Children.LEAF
0150:                            : new TreeModelChildren(model, treeModelRoot,
0151:                                    object);
0152:                } catch (UnknownTypeException e) {
0153:                    if (!(object instanceof  String)) {
0154:                        Throwable t = ErrorManager.getDefault().annotate(e,
0155:                                "Model: " + model);
0156:                        ErrorManager.getDefault().notify(
0157:                                ErrorManager.INFORMATIONAL, t);
0158:                    }
0159:                    return Children.LEAF;
0160:                }
0161:            }
0162:
0163:            public String getShortDescription() {
0164:                try {
0165:                    String shortDescription = model.getShortDescription(object);
0166:                    if (shortDescription != null) {
0167:                        shortDescription = adjustHTML(shortDescription);
0168:                    }
0169:                    return shortDescription;
0170:                } catch (UnknownTypeException e) {
0171:                    if (!(object instanceof  String)) {
0172:                        Throwable t = ErrorManager.getDefault().annotate(e,
0173:                                "Model: " + model);
0174:                        ErrorManager.getDefault().notify(
0175:                                ErrorManager.INFORMATIONAL, t);
0176:                    }
0177:                    return null;
0178:                }
0179:            }
0180:
0181:            public String getHtmlDisplayName() {
0182:                return htmlDisplayName;
0183:            }
0184:
0185:            public Action[] getActions(boolean context) {
0186:                if (context)
0187:                    return treeModelRoot.getRootNode().getActions(false);
0188:                try {
0189:                    return model.getActions(object);
0190:                } catch (UnknownTypeException e) {
0191:                    // NodeActionsProvider is voluntary
0192:                    return new Action[0];
0193:                }
0194:            }
0195:
0196:            public Action getPreferredAction() {
0197:                return new AbstractAction() {
0198:                    public void actionPerformed(ActionEvent e) {
0199:                        try {
0200:                            model.performDefaultAction(object);
0201:                        } catch (UnknownTypeException ex) {
0202:                            // NodeActionsProvider is voluntary
0203:                        }
0204:                    }
0205:                };
0206:            }
0207:
0208:            public boolean canDestroy() {
0209:                try {
0210:                    Action[] as = model.getActions(object);
0211:                    int i, k = as.length;
0212:                    for (i = 0; i < k; i++) {
0213:                        if (as[i] == null)
0214:                            continue;
0215:                        Object key = as[i].getValue(Action.ACCELERATOR_KEY);
0216:                        if ((key != null)
0217:                                && (key
0218:                                        .equals(KeyStroke
0219:                                                .getKeyStroke("DELETE"))))
0220:                            return as[i].isEnabled();
0221:                    }
0222:                    return false;
0223:                } catch (UnknownTypeException e) {
0224:                    // NodeActionsProvider is voluntary
0225:                    return false;
0226:                }
0227:            }
0228:
0229:            public boolean canCopy() {
0230:                try {
0231:                    return model.canCopy(object);
0232:                } catch (UnknownTypeException e) {
0233:                    Throwable t = ErrorManager.getDefault().annotate(e,
0234:                            "Model: " + model);
0235:                    ErrorManager.getDefault().notify(
0236:                            ErrorManager.INFORMATIONAL, t);
0237:                    return false;
0238:                }
0239:            }
0240:
0241:            public boolean canCut() {
0242:                try {
0243:                    return model.canCut(object);
0244:                } catch (UnknownTypeException e) {
0245:                    Throwable t = ErrorManager.getDefault().annotate(e,
0246:                            "Model: " + model);
0247:                    ErrorManager.getDefault().notify(
0248:                            ErrorManager.INFORMATIONAL, t);
0249:                    return false;
0250:                }
0251:            }
0252:
0253:            public void destroy() {
0254:                try {
0255:                    Action[] as = model.getActions(object);
0256:                    int i, k = as.length;
0257:                    for (i = 0; i < k; i++) {
0258:                        if (as[i] == null)
0259:                            continue;
0260:                        Object key = as[i].getValue(Action.ACCELERATOR_KEY);
0261:                        if ((key != null)
0262:                                && (key
0263:                                        .equals(KeyStroke
0264:                                                .getKeyStroke("DELETE")))) {
0265:                            as[i].actionPerformed(null);
0266:                            return;
0267:                        }
0268:                    }
0269:                } catch (UnknownTypeException e) {
0270:                    Throwable t = ErrorManager.getDefault().annotate(e,
0271:                            "Model: " + model);
0272:                    ErrorManager.getDefault().notify(
0273:                            ErrorManager.INFORMATIONAL, t);
0274:                }
0275:            }
0276:
0277:            // other methods ...........................................................
0278:
0279:            void setObject(Object o) {
0280:                setObjectNoRefresh(o);
0281:                refresh();
0282:            }
0283:
0284:            private void setObjectNoRefresh(Object o) {
0285:                object = o;
0286:                Children ch = getChildren();
0287:                if (ch instanceof  TreeModelChildren)
0288:                    ((TreeModelChildren) ch).object = o;
0289:            }
0290:
0291:            public Object getObject() {
0292:                return object;
0293:            }
0294:
0295:            private Task task;
0296:
0297:            void refresh() {
0298:                // 1) empty cache
0299:                synchronized (properties) {
0300:                    properties.clear();
0301:                }
0302:
0303:                // 2) refresh name, displayName and iconBase
0304:                if (task == null) {
0305:                    task = getRequestProcessor().create(new Runnable() {
0306:                        public void run() {
0307:                            refreshNode();
0308:                            fireShortDescriptionChange(null, null);
0309:
0310:                            // 3) refresh children
0311:                            refreshTheChildren(true);
0312:                        }
0313:                    });
0314:                }
0315:                task.schedule(0);
0316:            }
0317:
0318:            void refresh(int changeMask) {
0319:                if (changeMask == 0xFFFFFFFF) {
0320:                    refresh();
0321:                    return;
0322:                }
0323:                if ((ModelEvent.NodeChanged.DISPLAY_NAME_MASK & changeMask) != 0) {
0324:                    try {
0325:                        String name = model.getDisplayName(object);
0326:                        if (name == null) {
0327:                            Throwable t = new NullPointerException("Model: "
0328:                                    + model + ".getDisplayName (" + object
0329:                                    + ") = null!");
0330:                            ErrorManager.getDefault().notify(t);
0331:                        }
0332:                        setName(name, false);
0333:                    } catch (UnknownTypeException e) {
0334:                        Throwable t = ErrorManager.getDefault().annotate(e,
0335:                                "Model: " + model);
0336:                        ErrorManager.getDefault().notify(
0337:                                ErrorManager.INFORMATIONAL, t);
0338:                    }
0339:                } else if ((ModelEvent.NodeChanged.ICON_MASK & changeMask) != 0) {
0340:                    try {
0341:                        String iconBase = model
0342:                                .getIconBaseWithExtension(object);
0343:                        if (iconBase != null)
0344:                            setIconBaseWithExtension(iconBase);
0345:                        else
0346:                            setIconBaseWithExtension("org/openide/resources/actions/empty.gif");
0347:                    } catch (UnknownTypeException e) {
0348:                        Throwable t = ErrorManager.getDefault().annotate(e,
0349:                                "Model: " + model);
0350:                        ErrorManager.getDefault().notify(
0351:                                ErrorManager.INFORMATIONAL, t);
0352:                    }
0353:                } else if ((ModelEvent.NodeChanged.SHORT_DESCRIPTION_MASK & changeMask) != 0) {
0354:                    fireShortDescriptionChange(null, null);
0355:                } else if ((ModelEvent.NodeChanged.CHILDREN_MASK & changeMask) != 0) {
0356:                    getRequestProcessor().post(new Runnable() {
0357:                        public void run() {
0358:                            refreshTheChildren(false);
0359:                        }
0360:                    });
0361:                } else {
0362:                    refresh();
0363:                }
0364:            }
0365:
0366:            private static RequestProcessor requestProcessor;
0367:
0368:            static RequestProcessor getRequestProcessor() {
0369:                if (requestProcessor == null)
0370:                    requestProcessor = new RequestProcessor("TreeModel", 1);
0371:                return requestProcessor;
0372:            }
0373:
0374:            private void setName(String name, boolean italics) {
0375:                // XXX HACK: HTMLDisplayName is missing in the models!
0376:                String oldHtmlDisplayName = htmlDisplayName;
0377:                String oldDisplayName = getDisplayName();
0378:
0379:                String newDisplayName;
0380:                if (name.startsWith("<html>")) {
0381:                    htmlDisplayName = name;
0382:                    newDisplayName = removeHTML(name);
0383:                } else {
0384:                    htmlDisplayName = null;
0385:                    newDisplayName = name;
0386:                }
0387:                if ((oldDisplayName == null)
0388:                        || !oldDisplayName.equals(newDisplayName)) {
0389:                    setDisplayName(newDisplayName);
0390:                } else {
0391:                    if (oldHtmlDisplayName != null
0392:                            && !oldHtmlDisplayName.equals(htmlDisplayName)
0393:                            || htmlDisplayName != null
0394:                            && !htmlDisplayName.equals(oldHtmlDisplayName)) {
0395:
0396:                        // Display names are equal, but HTML display names differ!
0397:                        // We hope that this is sufficient to refresh the HTML display name:
0398:                        fireDisplayNameChange(oldDisplayName + "_HACK",
0399:                                getDisplayName());
0400:                    }
0401:                }
0402:            }
0403:
0404:            private void refreshNode() {
0405:                try {
0406:                    String name = model.getDisplayName(object);
0407:                    if (name == null) {
0408:                        Throwable t = new NullPointerException("Model: "
0409:                                + model + ".getDisplayName (" + object
0410:                                + ") = null!");
0411:                        ErrorManager.getDefault().notify(t);
0412:                    }
0413:                    setName(name, false);
0414:                    String iconBase = null;
0415:                    if (model.getRoot() != object) {
0416:                        iconBase = model.getIconBaseWithExtension(object);
0417:                    }
0418:                    if (iconBase != null)
0419:                        setIconBaseWithExtension(iconBase);
0420:                    else
0421:                        setIconBaseWithExtension("org/openide/resources/actions/empty.gif");
0422:                    firePropertyChange(null, null, null);
0423:                } catch (UnknownTypeException e) {
0424:                    Throwable t = ErrorManager.getDefault().annotate(e,
0425:                            "Model: " + model);
0426:                    ErrorManager.getDefault().notify(
0427:                            ErrorManager.INFORMATIONAL, t);
0428:                }
0429:            }
0430:
0431:            void refreshColumn(String column) {
0432:                synchronized (properties) {
0433:                    properties.remove(column);
0434:                    properties.remove(column + "#html");
0435:                }
0436:                firePropertyChange(column, null, null);
0437:            }
0438:
0439:            private void refreshTheChildren(boolean refreshSubNodes) {
0440:                Children ch = getChildren();
0441:                try {
0442:                    if (ch instanceof  TreeModelChildren) {
0443:                        if (model.isLeaf(object)) {
0444:                            setChildren(Children.LEAF);
0445:                        } else {
0446:                            ((TreeModelChildren) ch)
0447:                                    .refreshChildren(refreshSubNodes);
0448:                        }
0449:                    } else if (!model.isLeaf(object)) {
0450:                        setChildren(new TreeModelChildren(model, treeModelRoot,
0451:                                object));
0452:                    }
0453:                } catch (UnknownTypeException utex) {
0454:                    // not known - do not change children
0455:                    if (!(object instanceof  String)) {
0456:                        Throwable t = ErrorManager.getDefault().annotate(utex,
0457:                                "Model: " + model);
0458:                        ErrorManager.getDefault().notify(
0459:                                ErrorManager.INFORMATIONAL, t);
0460:                    }
0461:                    setChildren(Children.LEAF);
0462:                }
0463:            }
0464:
0465:            private static String htmlValue(String name) {
0466:                if (!(name.length() > 6 && name.substring(0, 6)
0467:                        .equalsIgnoreCase("<html>")))
0468:                    return null;
0469:                if (name.length() > MAX_HTML_LENGTH) {
0470:                    int endTagsPos = findEndTagsPos(name);
0471:                    String ending = name.substring(endTagsPos + 1);
0472:                    name = name.substring(0, MAX_HTML_LENGTH - 3
0473:                            - ending.length());
0474:                    // Check whether we haven't cut "&...;" in between:
0475:                    int n = name.length();
0476:                    for (int i = n - 1; i > n - 6; i--) {
0477:                        if (name.charAt(i) == ';') {
0478:                            break; // We have an end of the group
0479:                        }
0480:                        if (name.charAt(i) == '&') {
0481:                            name = name.substring(0, i);
0482:                            break;
0483:                        }
0484:                    }
0485:                    name += "..." + ending;
0486:                }
0487:                return adjustHTML(name);
0488:            }
0489:
0490:            private static int findEndTagsPos(String s) {
0491:                int openings = 0;
0492:                int i;
0493:                for (i = s.length() - 1; i >= 0; i--) {
0494:                    if (s.charAt(i) == '>')
0495:                        openings++;
0496:                    else if (s.charAt(i) == '<')
0497:                        openings--;
0498:                    else if (openings == 0)
0499:                        break;
0500:                }
0501:                return i;
0502:            }
0503:
0504:            private static String removeHTML(String text) {
0505:                if (!(text.length() > 6 && text.substring(0, 6)
0506:                        .equalsIgnoreCase("<html>"))) {
0507:                    return text;
0508:                }
0509:                text = text.replaceAll("<i>", "");
0510:                text = text.replaceAll("</i>", "");
0511:                text = text.replaceAll("<b>", "");
0512:                text = text.replaceAll("</b>", "");
0513:                text = text.replaceAll("<html>", "");
0514:                text = text.replaceAll("</html>", "");
0515:                text = text.replaceAll("</font>", "");
0516:                int i = text.indexOf("<font");
0517:                while (i >= 0) {
0518:                    int j = text.indexOf(">", i);
0519:                    text = text.substring(0, i) + text.substring(j + 1);
0520:                    i = text.indexOf("<font");
0521:                }
0522:                text = text.replaceAll("&lt;", "<");
0523:                text = text.replaceAll("&gt;", ">");
0524:                text = text.replaceAll("&amp;", "&");
0525:                return text;
0526:            }
0527:
0528:            /** Adjusts HTML text so that it's rendered correctly.
0529:             * In particular, this assures that white characters are visible.
0530:             */
0531:            private static String adjustHTML(String text) {
0532:                text = text.replaceAll(java.util.regex.Matcher
0533:                        .quoteReplacement("\\"), "\\\\\\\\");
0534:                StringBuffer sb = null;
0535:                int j = 0;
0536:                for (int i = 0; i < text.length(); i++) {
0537:                    char c = text.charAt(i);
0538:                    String replacement = null;
0539:                    if (c == '\n') {
0540:                        replacement = "\\n";
0541:                    } else if (c == '\r') {
0542:                        replacement = "\\r";
0543:                    } else if (c == '\f') {
0544:                        replacement = "\\f";
0545:                    } else if (c == '\b') {
0546:                        replacement = "\\b";
0547:                    }
0548:                    if (replacement != null) {
0549:                        if (sb == null) {
0550:                            sb = new StringBuffer(text.substring(0, i));
0551:                        } else {
0552:                            sb.append(text.substring(j, i));
0553:                        }
0554:                        sb.append(replacement);
0555:                        j = i + 1;
0556:                    }
0557:                }
0558:                if (sb == null) {
0559:                    return text;
0560:                } else {
0561:                    sb.append(text.substring(j));
0562:                    return sb.toString();
0563:                }
0564:            }
0565:
0566:            public boolean canRename() {
0567:                try {
0568:                    return model.canRename(object);
0569:                } catch (UnknownTypeException e) {
0570:                    Throwable t = ErrorManager.getDefault().annotate(e,
0571:                            "Model: " + model);
0572:                    ErrorManager.getDefault().notify(
0573:                            ErrorManager.INFORMATIONAL, t);
0574:                    return false;
0575:                }
0576:            }
0577:
0578:            public void setName(String s) {
0579:                try {
0580:                    model.setName(object, s);
0581:                    super .setName(s);
0582:                } catch (UnknownTypeException e) {
0583:                    Throwable t = ErrorManager.getDefault().annotate(e,
0584:                            "Model: " + model);
0585:                    ErrorManager.getDefault().notify(
0586:                            ErrorManager.INFORMATIONAL, t);
0587:                }
0588:            }
0589:
0590:            public Transferable clipboardCopy() throws IOException {
0591:                Transferable t;
0592:                try {
0593:                    t = model.clipboardCopy(object);
0594:                } catch (UnknownTypeException e) {
0595:                    Throwable th = ErrorManager.getDefault().annotate(e,
0596:                            "Model: " + model);
0597:                    ErrorManager.getDefault().notify(
0598:                            ErrorManager.INFORMATIONAL, th);
0599:                    t = null;
0600:                }
0601:                if (t == null) {
0602:                    return super .clipboardCopy();
0603:                } else {
0604:                    return t;
0605:                }
0606:            }
0607:
0608:            public Transferable clipboardCut() throws IOException {
0609:                Transferable t;
0610:                try {
0611:                    t = model.clipboardCut(object);
0612:                } catch (UnknownTypeException e) {
0613:                    Throwable th = ErrorManager.getDefault().annotate(e,
0614:                            "Model: " + model);
0615:                    ErrorManager.getDefault().notify(
0616:                            ErrorManager.INFORMATIONAL, th);
0617:                    t = null;
0618:                }
0619:                if (t == null) {
0620:                    return super .clipboardCut();
0621:                } else {
0622:                    return t;
0623:                }
0624:            }
0625:
0626:            /*
0627:            public Transferable drag() throws IOException {
0628:                Transferable t;
0629:                try {
0630:                    t = model.drag(object);
0631:                } catch (UnknownTypeException e) {
0632:                    Throwable th = ErrorManager.getDefault().annotate(e, "Model: "+model);
0633:                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, th);
0634:                    t = null;
0635:                }
0636:                if (t == null) {
0637:                    return super.drag();
0638:                } else {
0639:                    return t;
0640:                }
0641:            }
0642:             */
0643:
0644:            public void createPasteTypes(Transferable t, List<PasteType> l) {
0645:                PasteType[] p;
0646:                try {
0647:                    p = model.getPasteTypes(object, t);
0648:                } catch (UnknownTypeException e) {
0649:                    Throwable th = ErrorManager.getDefault().annotate(e,
0650:                            "Model: " + model);
0651:                    ErrorManager.getDefault().notify(
0652:                            ErrorManager.INFORMATIONAL, th);
0653:                    p = null;
0654:                }
0655:                if (p == null) {
0656:                    super .createPasteTypes(t, l);
0657:                } else {
0658:                    l.addAll(Arrays.asList(p));
0659:                }
0660:            }
0661:
0662:            /*
0663:            public PasteType getDropType(Transferable t, int action, int index) {
0664:                PasteType p;
0665:                try {
0666:                    p = model.getDropType(object, t, action, index);
0667:                } catch (UnknownTypeException e) {
0668:                    Throwable th = ErrorManager.getDefault().annotate(e, "Model: "+model);
0669:                    ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, th);
0670:                    p = null;
0671:                }
0672:                if (p == null) {
0673:                    return super.getDropType(t, action, index);
0674:                } else {
0675:                    return p;
0676:                }
0677:            }
0678:             */
0679:
0680:            // innerclasses ............................................................
0681:            /** Special locals subnodes (children) */
0682:            private static final class TreeModelChildren extends
0683:                    Children.Keys<Object> implements  LazyEvaluator.Evaluable {
0684:
0685:                private boolean initialezed = false;
0686:                private Models.CompoundModel model;
0687:                private TreeModelRoot treeModelRoot;
0688:                private Object object;
0689:                private WeakHashMap<Object, WeakReference<TreeModelNode>> objectToNode = new WeakHashMap<Object, WeakReference<TreeModelNode>>();
0690:                private int[] evaluated = { 0 }; // 0 - not yet, 1 - evaluated, -1 - timeouted
0691:                private Object[] children_evaluated;
0692:                private boolean refreshingSubNodes = true;
0693:                private boolean refreshingStarted = true;
0694:
0695:                private static final Object WAIT_KEY = new Object();
0696:
0697:                TreeModelChildren(Models.CompoundModel model,
0698:                        TreeModelRoot treeModelRoot, Object object) {
0699:                    this .model = model;
0700:                    this .treeModelRoot = treeModelRoot;
0701:                    this .object = object;
0702:                }
0703:
0704:                protected void addNotify() {
0705:                    initialezed = true;
0706:                    refreshChildren(true);
0707:                }
0708:
0709:                protected void removeNotify() {
0710:                    initialezed = false;
0711:                    setKeys(Collections.emptySet());
0712:                }
0713:
0714:                void refreshChildren(boolean refreshSubNodes) {
0715:                    if (!initialezed)
0716:                        return;
0717:
0718:                    refreshLazyChildren(refreshSubNodes);
0719:                }
0720:
0721:                public void evaluateLazily(Runnable evaluatedNotify) {
0722:                    synchronized (evaluated) {
0723:                        refreshingStarted = false;
0724:                    }
0725:                    Object[] ch;
0726:                    try {
0727:                        int count = model.getChildrenCount(object);
0728:                        ch = model.getChildren(object, 0, count);
0729:                    } catch (UnknownTypeException e) {
0730:                        ch = new Object[0];
0731:                        if (!(object instanceof  String)) {
0732:                            Throwable t = ErrorManager.getDefault().annotate(e,
0733:                                    "Model: " + model);
0734:                            ErrorManager.getDefault().notify(
0735:                                    ErrorManager.INFORMATIONAL, t);
0736:                        }
0737:                    } catch (ThreadDeath td) {
0738:                        throw td;
0739:                    } catch (Throwable t) {
0740:                        // recover from defect in getChildren()
0741:                        // Otherwise there would remain "Please wait..." node.
0742:                        ErrorManager.getDefault().notify(t);
0743:                        ch = new Object[0];
0744:                    }
0745:                    evaluatedNotify.run();
0746:                    boolean fire;
0747:                    synchronized (evaluated) {
0748:                        int eval = evaluated[0];
0749:                        if (refreshingStarted) {
0750:                            fire = false;
0751:                        } else {
0752:                            fire = evaluated[0] == -1;
0753:                            if (!fire) {
0754:                                children_evaluated = ch;
0755:                            }
0756:                            evaluated[0] = 1;
0757:                            evaluated.notifyAll();
0758:                        }
0759:                        //System.err.println(this.hashCode()+" evaluateLazily() ready, evaluated[0] = "+eval+" => fire = "+fire+", refreshingStarted = "+refreshingStarted+", children_evaluated = "+(children_evaluated != null));
0760:                    }
0761:                    if (fire) {
0762:                        applyChildren(ch, refreshingSubNodes);
0763:                    }
0764:                }
0765:
0766:                private void refreshLazyChildren(boolean refreshSubNodes) {
0767:                    synchronized (evaluated) {
0768:                        evaluated[0] = 0;
0769:                        refreshingStarted = true;
0770:                        this .refreshingSubNodes = refreshSubNodes;
0771:                        //System.err.println(this.hashCode()+" refreshLazyChildren() started = true, evaluated = 0");
0772:                    }
0773:                    // It's refresh => do not check for this children already being evaluated
0774:                    treeModelRoot.getChildrenEvaluator().evaluate(this , false);
0775:                    Object[] ch;
0776:                    synchronized (evaluated) {
0777:                        if (evaluated[0] != 1) {
0778:                            try {
0779:                                evaluated.wait(200);
0780:                            } catch (InterruptedException iex) {
0781:                            }
0782:                            if (evaluated[0] != 1) {
0783:                                evaluated[0] = -1; // timeout
0784:                                ch = null;
0785:                            } else {
0786:                                ch = children_evaluated;
0787:                            }
0788:                        } else {
0789:                            ch = children_evaluated;
0790:                        }
0791:                        //System.err.println(this.hashCode()+" refreshLazyChildren() ending, evaluated[0] = "+evaluated[0]+", refreshingStarted = "+refreshingStarted+", children_evaluated = "+(children_evaluated != null)+", ch = "+(ch != null));
0792:                        // Do nothing when it's evaluated, but already unset.
0793:                        if (children_evaluated == null && evaluated[0] == 1)
0794:                            return;
0795:                        children_evaluated = null;
0796:                    }
0797:                    if (ch == null) {
0798:                        applyWaitChildren();
0799:                    } else {
0800:                        applyChildren(ch, refreshSubNodes);
0801:                    }
0802:                }
0803:
0804:                private void applyChildren(final Object[] ch,
0805:                        boolean refreshSubNodes) {
0806:                    //System.err.println(this.hashCode()+" applyChildren("+refreshSubNodes+")");
0807:                    int i, k = ch.length;
0808:                    WeakHashMap<Object, WeakReference<TreeModelNode>> newObjectToNode = new WeakHashMap<Object, WeakReference<TreeModelNode>>();
0809:                    for (i = 0; i < k; i++) {
0810:                        if (ch[i] == null) {
0811:                            throw (NullPointerException) ErrorManager
0812:                                    .getDefault().annotate(
0813:                                            new NullPointerException(),
0814:                                            "model: " + model + "\nparent: "
0815:                                                    + object);
0816:                        }
0817:                        WeakReference<TreeModelNode> wr = objectToNode
0818:                                .get(ch[i]);
0819:                        if (wr == null)
0820:                            continue;
0821:                        TreeModelNode tmn = wr.get();
0822:                        if (tmn == null)
0823:                            continue;
0824:                        if (refreshSubNodes) {
0825:                            tmn.setObject(ch[i]);
0826:                        } else {
0827:                            tmn.setObjectNoRefresh(ch[i]);
0828:                        }
0829:                        newObjectToNode.put(ch[i], wr);
0830:                    }
0831:                    objectToNode = newObjectToNode;
0832:                    setKeys(ch);
0833:
0834:                    SwingUtilities.invokeLater(new Runnable() {
0835:                        public void run() {
0836:                            int i, k = ch.length;
0837:                            for (i = 0; i < k; i++)
0838:                                try {
0839:                                    if (model.isExpanded(ch[i])) {
0840:                                        TreeTable treeTable = treeModelRoot
0841:                                                .getTreeTable();
0842:                                        if (treeTable.isExpanded(object)) {
0843:                                            // Expand the child only if the parent is expanded
0844:                                            treeTable.expandNode(ch[i]);
0845:                                        }
0846:                                    }
0847:                                } catch (UnknownTypeException ex) {
0848:                                }
0849:                        }
0850:                    });
0851:                }
0852:
0853:                private void applyWaitChildren() {
0854:                    //System.err.println(this.hashCode()+" applyWaitChildren()");
0855:                    setKeys(new Object[] { WAIT_KEY });
0856:                }
0857:
0858:                //        protected void destroyNodes (Node[] nodes) {
0859:                //            int i, k = nodes.length;
0860:                //            for (i = 0; i < k; i++) {
0861:                //                TreeModelNode tmn = (TreeModelNode) nodes [i];
0862:                //                String name = null;
0863:                //                try {
0864:                //                    name = model.getDisplayName (tmn.object);
0865:                //                } catch (UnknownTypeException e) {
0866:                //                }
0867:                //                if (name != null)
0868:                //                    nameToChild.remove (name);
0869:                //            }
0870:                //        }
0871:
0872:                protected Node[] createNodes(Object object) {
0873:                    if (object == WAIT_KEY) {
0874:                        AbstractNode n = new AbstractNode(Children.LEAF);
0875:                        n.setName(NbBundle.getMessage(TreeModelNode.class,
0876:                                "WaitNode"));
0877:                        n
0878:                                .setIconBaseWithExtension("org/netbeans/modules/viewmodel/wait.gif");
0879:                        return new Node[] { n };
0880:                    }
0881:                    if (object instanceof  Exception)
0882:                        return new Node[] { new ExceptionNode(
0883:                                (Exception) object) };
0884:                    TreeModelNode tmn = new TreeModelNode(model, treeModelRoot,
0885:                            object);
0886:                    objectToNode.put(object, new WeakReference<TreeModelNode>(
0887:                            tmn));
0888:                    return new Node[] { tmn };
0889:                }
0890:            } // ItemChildren
0891:
0892:            private class MyProperty extends PropertySupport implements 
0893:                    LazyEvaluator.Evaluable {
0894:
0895:                private final String EVALUATING_STR = NbBundle.getMessage(
0896:                        TreeModelNode.class, "EvaluatingProp");
0897:                private String id;
0898:                private ColumnModel columnModel;
0899:                private boolean nodeColumn;
0900:                private TreeModelRoot treeModelRoot;
0901:                private int[] evaluated = { 0 }; // 0 - not yet, 1 - evaluated, -1 - timeouted
0902:
0903:                MyProperty(ColumnModel columnModel, TreeModelRoot treeModelRoot) {
0904:                    super (columnModel.getID(),
0905:                            (columnModel.getType() == null) ? String.class
0906:                                    : columnModel.getType(), columnModel
0907:                                    .getDisplayName(), columnModel
0908:                                    .getShortDescription(), true, true);
0909:                    this .columnModel = columnModel;
0910:                    this .nodeColumn = columnModel.getType() == null;
0911:                    this .treeModelRoot = treeModelRoot;
0912:                    id = columnModel.getID();
0913:                }
0914:
0915:                /* Can write the value of the property.
0916:                 * Returns the value passed into constructor.
0917:                 * @return <CODE>true</CODE> if the read of the value is supported
0918:                 */
0919:                public boolean canWrite() {
0920:                    if (nodeColumn)
0921:                        return false;
0922:                    try {
0923:                        return !model.isReadOnly(object, columnModel.getID());
0924:                    } catch (UnknownTypeException e) {
0925:                        if (!(object instanceof  String)) {
0926:                            Throwable t = ErrorManager.getDefault().annotate(
0927:                                    e,
0928:                                    "Column id:" + columnModel.getID()
0929:                                            + "\nModel: " + model);
0930:                            ErrorManager.getDefault().notify(
0931:                                    ErrorManager.INFORMATIONAL, t);
0932:                        }
0933:                        return false;
0934:                    }
0935:                }
0936:
0937:                public void evaluateLazily(Runnable evaluatedNotify) {
0938:                    Object value = "";
0939:                    String htmlValue = null;
0940:                    String nonHtmlValue = null;
0941:                    try {
0942:                        value = model.getValueAt(object, id);
0943:                        //System.out.println("  evaluateLazily("+TreeModelNode.this.getDisplayName()+", "+id+"): have value = "+value);
0944:                        if (value instanceof  String) {
0945:                            htmlValue = htmlValue((String) value);
0946:                            nonHtmlValue = removeHTML((String) value);
0947:                        }
0948:                    } catch (UnknownTypeException e) {
0949:                        if (!(object instanceof  String)) {
0950:                            e.printStackTrace();
0951:                            System.out.println("  Column id:"
0952:                                    + columnModel.getID());
0953:                            System.out.println(model);
0954:                            System.out.println();
0955:                        }
0956:                    } catch (Throwable t) {
0957:                        t.printStackTrace();
0958:                    } finally {
0959:                        evaluatedNotify.run();
0960:                        boolean fire;
0961:                        synchronized (properties) {
0962:                            if (value instanceof  String) {
0963:                                properties.put(id, nonHtmlValue);
0964:                                properties.put(id + "#html", htmlValue);
0965:                            } else {
0966:                                properties.put(id, value);
0967:                            }
0968:                            synchronized (evaluated) {
0969:                                fire = evaluated[0] == -1;
0970:                                evaluated[0] = 1;
0971:                                evaluated.notifyAll();
0972:                            }
0973:                        }
0974:                        //System.out.println("\nTreeModelNode.evaluateLazily("+TreeModelNode.this.getDisplayName()+", "+id+"): value = "+value+", fire = "+fire);
0975:                        if (fire) {
0976:                            firePropertyChange(id, null, value);
0977:                            refreshTheChildren(true);
0978:                        }
0979:
0980:                    }
0981:                }
0982:
0983:                public synchronized Object getValue() { // Sync the calls
0984:                    if (nodeColumn) {
0985:                        return TreeModelNode.this .getDisplayName();
0986:                    }
0987:                    // 1) return value from cache
0988:                    synchronized (properties) {
0989:                        //System.out.println("getValue("+TreeModelNode.this.getDisplayName()+", "+id+"): contains = "+properties.containsKey (id)+", value = "+properties.get (id));
0990:                        if (properties.containsKey(id))
0991:                            return properties.get(id);
0992:                    }
0993:
0994:                    synchronized (evaluated) {
0995:                        evaluated[0] = 0;
0996:                    }
0997:                    treeModelRoot.getValuesEvaluator().evaluate(this );
0998:
0999:                    Object ret = null;
1000:                    boolean refreshChildren = false;
1001:
1002:                    synchronized (evaluated) {
1003:                        if (evaluated[0] != 1) {
1004:                            try {
1005:                                evaluated.wait(25);
1006:                            } catch (InterruptedException iex) {
1007:                            }
1008:                            if (evaluated[0] != 1) {
1009:                                evaluated[0] = -1; // timeout
1010:                                ret = EVALUATING_STR;
1011:                            } else {
1012:                                refreshChildren = true;
1013:                            }
1014:                        }
1015:                    }
1016:                    if (ret == null) {
1017:                        synchronized (properties) {
1018:                            ret = properties.get(id);
1019:                        }
1020:                    }
1021:
1022:                    if (refreshChildren) {
1023:                        getRequestProcessor().post(new Runnable() {
1024:                            public void run() {
1025:                                refreshTheChildren(true);
1026:                            }
1027:                        });
1028:                    }
1029:                    if (ret == EVALUATING_STR && getValueType() != null
1030:                            && getValueType() != String.class) {
1031:                        ret = null; // Must not provide String when the property type is different.
1032:                        // htmlDisplayValue attr will assure that the Evaluating str is there.
1033:                    }
1034:                    return ret;
1035:                }
1036:
1037:                public Object getValue(String attributeName) {
1038:                    if (attributeName.equals("htmlDisplayValue")) {
1039:                        if (nodeColumn) {
1040:                            return TreeModelNode.this .getHtmlDisplayName();
1041:                        }
1042:                        synchronized (evaluated) {
1043:                            if (evaluated[0] != 1) {
1044:                                return "<html><font color=\"0000CC\">"
1045:                                        + EVALUATING_STR + "</font></html>";
1046:                            }
1047:                        }
1048:                        synchronized (properties) {
1049:                            return properties.get(id + "#html");
1050:                        }
1051:                    }
1052:                    return super .getValue(attributeName);
1053:                }
1054:
1055:                public String getShortDescription() {
1056:                    if (nodeColumn) {
1057:                        return TreeModelNode.this .getShortDescription();
1058:                    }
1059:                    synchronized (properties) {
1060:                        if (!properties.containsKey(id)) {
1061:                            return null; // The same as value => EVALUATING_STR
1062:                        }
1063:                    }
1064:                    try {
1065:                        javax.swing.JToolTip tooltip = new javax.swing.JToolTip();
1066:                        tooltip
1067:                                .putClientProperty("getShortDescription",
1068:                                        object); // NOI18N
1069:                        Object tooltipObj = model.getValueAt(tooltip, id);
1070:                        if (tooltipObj == null) {
1071:                            return null;
1072:                        } else {
1073:                            return adjustHTML(tooltipObj.toString());
1074:                        }
1075:                    } catch (UnknownTypeException e) {
1076:                        // Ignore models that do not define tooltips for values.
1077:                        return null;
1078:                    }
1079:                }
1080:
1081:                public void setValue(Object v) throws IllegalAccessException,
1082:                        IllegalArgumentException,
1083:                        java.lang.reflect.InvocationTargetException {
1084:                    try {
1085:                        model.setValueAt(object, id, v);
1086:                        synchronized (properties) {
1087:                            properties.put(id, v);
1088:                        }
1089:                        firePropertyChange(id, null, null);
1090:                    } catch (UnknownTypeException e) {
1091:                        Throwable t = ErrorManager.getDefault().annotate(
1092:                                e,
1093:                                "Column id:" + columnModel.getID()
1094:                                        + "\nModel: " + model);
1095:                        ErrorManager.getDefault().notify(
1096:                                ErrorManager.INFORMATIONAL, t);
1097:                    }
1098:                }
1099:
1100:                public PropertyEditor getPropertyEditor() {
1101:                    return columnModel.getPropertyEditor();
1102:                }
1103:            }
1104:
1105:            /** The single-threaded evaluator of lazy models. */
1106:            static class LazyEvaluator implements  Runnable {
1107:
1108:                /** Release the evaluator task after this time. */
1109:                private static final long EXPIRE_TIME = 60000L;
1110:
1111:                private List<Object> objectsToEvaluate = new LinkedList<Object>();
1112:                private Evaluable currentlyEvaluating;
1113:                private Task evalTask;
1114:
1115:                public LazyEvaluator() {
1116:                    evalTask = new RequestProcessor(
1117:                            "Debugger Values Evaluator", 1).post(this );
1118:                }
1119:
1120:                public void evaluate(Evaluable eval) {
1121:                    evaluate(eval, true);
1122:                }
1123:
1124:                public void evaluate(Evaluable eval, boolean checkForEvaluating) {
1125:                    synchronized (objectsToEvaluate) {
1126:                        for (Iterator it = objectsToEvaluate.iterator(); it
1127:                                .hasNext();) {
1128:                            if (eval == it.next())
1129:                                return; // Already scheduled
1130:                        }
1131:                        if (checkForEvaluating && currentlyEvaluating == eval)
1132:                            return; // Is being evaluated
1133:                        objectsToEvaluate.add(eval);
1134:                        objectsToEvaluate.notify();
1135:                        if (evalTask.isFinished()) {
1136:                            evalTask.schedule(0);
1137:                        }
1138:                    }
1139:                }
1140:
1141:                public void run() {
1142:                    while (true) {
1143:                        Evaluable eval;
1144:                        synchronized (objectsToEvaluate) {
1145:                            if (objectsToEvaluate.size() == 0) {
1146:                                try {
1147:                                    objectsToEvaluate.wait(EXPIRE_TIME);
1148:                                } catch (InterruptedException iex) {
1149:                                    return;
1150:                                }
1151:                                if (objectsToEvaluate.size() == 0) { // Expired
1152:                                    return;
1153:                                }
1154:                            }
1155:                            eval = (Evaluable) objectsToEvaluate.remove(0);
1156:                            currentlyEvaluating = eval;
1157:                        }
1158:                        Runnable evaluatedNotify = new Runnable() {
1159:                            public void run() {
1160:                                synchronized (objectsToEvaluate) {
1161:                                    currentlyEvaluating = null;
1162:                                }
1163:                            }
1164:                        };
1165:                        eval.evaluateLazily(evaluatedNotify);
1166:                    }
1167:                }
1168:
1169:                public interface Evaluable {
1170:
1171:                    public void evaluateLazily(Runnable evaluatedNotify);
1172:
1173:                }
1174:
1175:            }
1176:
1177:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.