This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 199742
Collapse All | Expand All

(-)a/ant.grammar/nbproject/project.xml (-1 / +1 lines)
Lines 100-106 Link Here
100
                    <compile-dependency/>
100
                    <compile-dependency/>
101
                    <run-dependency>
101
                    <run-dependency>
102
                        <release-version>2</release-version>
102
                        <release-version>2</release-version>
103
                        <specification-version>1.9.0</specification-version>
103
                        <specification-version>1.28.0</specification-version>
104
                    </run-dependency>
104
                    </run-dependency>
105
                </dependency>
105
                </dependency>
106
                <dependency>
106
                <dependency>
(-)a/ant.grammar/src/org/netbeans/modules/ant/grammar/AntGrammar.java (-14 / +28 lines)
Lines 45-50 Link Here
45
package org.netbeans.modules.ant.grammar;
45
package org.netbeans.modules.ant.grammar;
46
46
47
import java.io.IOException;
47
import java.io.IOException;
48
import java.net.URI;
48
import java.net.URL;
49
import java.net.URL;
49
import java.text.Collator;
50
import java.text.Collator;
50
import java.util.ArrayList;
51
import java.util.ArrayList;
Lines 66-71 Link Here
66
import org.netbeans.modules.xml.api.model.GrammarResult;
67
import org.netbeans.modules.xml.api.model.GrammarResult;
67
import org.netbeans.modules.xml.api.model.HintContext;
68
import org.netbeans.modules.xml.api.model.HintContext;
68
import org.netbeans.modules.xml.spi.dom.AbstractNode;
69
import org.netbeans.modules.xml.spi.dom.AbstractNode;
70
import org.netbeans.modules.xml.api.model.DescriptionSource;
69
import org.openide.filesystems.FileObject;
71
import org.openide.filesystems.FileObject;
70
import org.openide.filesystems.URLMapper;
72
import org.openide.filesystems.URLMapper;
71
import org.openide.util.Enumerations;
73
import org.openide.util.Enumerations;
Lines 395-418 Link Here
395
                case PROJECT:
397
                case PROJECT:
396
                case TARGET:
398
                case TARGET:
397
                    list.add(new MyElement(element) {
399
                    list.add(new MyElement(element) {
398
                        @Override public String getDescription() {
400
                        private URL manpage;
401
402
                        {
399
                            ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class);
403
                            ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class);
400
                            URL manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Tasks/" + element + ".html");
404
                            manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Tasks/" + element + ".html");
401
                            if (manpage == null) {
405
                            if (manpage == null) {
402
                                manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Types/" + element + ".html");
406
                                manpage = cl.getResource("org/apache/tools/ant/module/docs/ant-docs/Types/" + element + ".html");
403
                            }
407
                            }
404
                            if (manpage != null) {
405
                                FileObject f = URLMapper.findFileObject(manpage);
406
                                if (f != null) {
407
                                    try {
408
                                        return new String(f.asBytes(), FileEncodingQuery.getEncoding(f));
409
                                    } catch (IOException x) {
410
                                        LOG.log(Level.INFO, "Could not load " + manpage, x);
411
                                    }
412
                                }
413
                            }
414
                            return null;
415
                        }
408
                        }
409
410
                        @Override
411
                        public URL getContentURL() {
412
                            return manpage;
413
                        }
414
                        
415
                        
416
                    });
416
                    });
417
                    break;
417
                    break;
418
                default:
418
                default:
Lines 827-833 Link Here
827
827
828
    }
828
    }
829
829
830
    private static class MyElement extends AbstractResultNode implements Element {
830
    private static class MyElement extends AbstractResultNode implements Element, DescriptionSource {
831
831
832
        private String name;
832
        private String name;
833
833
Lines 850-856 Link Here
850
        public @Override String toString() {
850
        public @Override String toString() {
851
            return name;
851
            return name;
852
        }
852
        }
853
        
854
        @Override
855
        public DescriptionSource resolveLink(String link) {
856
            return null;
857
        }
858
        
859
        @Override
860
        public boolean isExternal() {
861
            return false;
862
        }
853
863
864
        @Override
865
        public URL getContentURL() {
866
            return null;
867
        }
854
    }
868
    }
855
869
856
    private static class MyAttr extends AbstractResultNode implements Attr {
870
    private static class MyAttr extends AbstractResultNode implements Attr {
(-)a/xml.core/nbproject/project.properties (-1 / +1 lines)
Lines 42-48 Link Here
42
42
43
javac.compilerargs=-Xlint -Xlint:-serial
43
javac.compilerargs=-Xlint -Xlint:-serial
44
javac.source=1.6
44
javac.source=1.6
45
spec.version.base=1.27.0
45
spec.version.base=1.28.0
46
is.autoload=true
46
is.autoload=true
47
47
48
javadoc.packages=\
48
javadoc.packages=\
(-)a/xml.core/nbproject/project.xml (+9 lines)
Lines 50-55 Link Here
50
            <code-name-base>org.netbeans.modules.xml.core</code-name-base>
50
            <code-name-base>org.netbeans.modules.xml.core</code-name-base>
51
            <module-dependencies>
51
            <module-dependencies>
52
                <dependency>
52
                <dependency>
53
                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
56
                    <run-dependency>
57
                        <release-version>1</release-version>
58
                        <specification-version>1.11</specification-version>
59
                    </run-dependency>
60
                </dependency>
61
                <dependency>
53
                    <code-name-base>org.netbeans.api.xml</code-name-base>
62
                    <code-name-base>org.netbeans.api.xml</code-name-base>
54
                    <build-prerequisite/>
63
                    <build-prerequisite/>
55
                    <compile-dependency/>
64
                    <compile-dependency/>
(-)a/xml.core/src/org/netbeans/modules/xml/api/model/DescriptionSource.java (+106 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.xml.api.model;
43
44
import java.net.URI;
45
import java.net.URL;
46
import org.netbeans.api.annotations.common.CheckForNull;
47
48
/**
49
 * Optional mixin interface, which can be implemented together with the
50
 * {@link GrammarResult} interface on the returned completion item. 
51
 * It allows to resolve links and provide description contents.
52
 * <p/>
53
 * Implementation may return {@code null} from {@link #getDescription} to 
54
 * indicate that the system should load contents from the URL supplied by {@link #getContentURL()}.
55
 * <p/>
56
 * The implementation may choose to provide the content URL to open within the IDE
57
 * or in an external browser. Any links will be resolved relatively to that URL.
58
 * For special cases, the implementation may resolve a link to another instance
59
 * of DescriptionSource by implementing {@link #resolveLink}.
60
 * <p/>
61
 * If both {@link #getDescription} and {@link #getContentURL} return null, there's
62
 * no description at all for the {@link GrammarResult}.
63
 * 
64
 * @author sdedic
65
 * @since 1.28
66
 */
67
public interface DescriptionSource {
68
    /**
69
     * Provides text of the description. If the method returns null, the 
70
     * IDE will try to load contents of the {@link #getContentURL()} and use that
71
     * as a description.
72
     * 
73
     * @return Description contents or {@code null}, if contents should be loaded
74
     * from {@link #getContentURL}.
75
     */
76
    @CheckForNull
77
    public String  getDescription();
78
79
    /**
80
     * True, if the description can be opened by an external browser, following the
81
     * {@link #getContentURL}.
82
     * 
83
     * @return true, if the content URL can be used outside of the IDE
84
     */
85
    public boolean isExternal();
86
    
87
    /**
88
     * Returns URL for the content, so it can be retrieved. If this URL is provided,
89
     * any link not resolved by {@link #resolveLink} will be treated
90
     * as relative to this content URL.
91
     * 
92
     * @return URL of the description content
93
     */
94
    @CheckForNull
95
    public URL  getContentURL();
96
    
97
    /**
98
     * Resolves a link in the documentation to another DescriptionSource. Can
99
     * return null, if the link cannot be resolved.
100
     * 
101
     * @param link link found in the text
102
     * @return resolved description, or {@code null}
103
     */
104
    @CheckForNull
105
    public DescriptionSource  resolveLink(String link);
106
}
(-)a/xml.core/src/org/netbeans/modules/xml/api/model/GrammarResult.java (-1 / +21 lines)
Lines 46-51 Link Here
46
46
47
import org.w3c.dom.Node;
47
import org.w3c.dom.Node;
48
import javax.swing.Icon;
48
import javax.swing.Icon;
49
import org.netbeans.api.annotations.common.CheckForNull;
49
50
50
/**
51
/**
51
 * It represents additonal properties of a result option.
52
 * It represents additonal properties of a result option.
Lines 77-85 Link Here
77
    String getDisplayName();
78
    String getDisplayName();
78
79
79
    /**
80
    /**
81
     * Returns contents of a description, text suitable for displaying as a tooltip
82
     * that simplifies decision. {@code null} may be returned if no description is available.
83
     * The decription is interpreted as HTML markup. If the markup contains relative
84
     * links or special URIs, implement also {@link DescriptionSource} to resolve 
85
     * those links.
86
     * <p/>
87
     * If {@link DescriptionSource} is implemented on the same object, this method
88
     * may return null to indicate the content should be <b>loaded by the infrastructure</b>
89
     * from the URL returned by {@link DescriptionSource#getContentURL()}. If both
90
     * {@code getDescription()} and {@code DescriptionSource.getContentURL()} return
91
     * null, no description is displayed in the tooltip.
92
     * <p/>
93
     * Implementors may prefer implementing the {@code DescriptionSource} and
94
     * loading from the {@link DescriptionSource#getContentURL()} if the
95
     * description resides in a separate file included in the JAR or in the XML layer.
96
     * 
80
     * @return provide additional information simplifing decision
97
     * @return provide additional information simplifing decision
81
     * (suitable for tooltip) or <code>null</code>
98
     * (suitable for tooltip) or {@code null}.
99
     * 
100
     * @since 1.28 - DescriptionSource extension
82
     */
101
     */
102
    @CheckForNull
83
    String getDescription();
103
    String getDescription();
84
104
85
    /**
105
    /**
(-)a/xml.text/nbproject/project.xml (-1 / +10 lines)
Lines 184-195 Link Here
184
                    </run-dependency>
184
                    </run-dependency>
185
                </dependency>
185
                </dependency>
186
                <dependency>
186
                <dependency>
187
                    <code-name-base>org.netbeans.modules.queries</code-name-base>
188
                    <build-prerequisite/>
189
                    <compile-dependency/>
190
                    <run-dependency>
191
                        <release-version>1</release-version>
192
                        <specification-version>1.25</specification-version>
193
                    </run-dependency>
194
                </dependency>
195
                <dependency>
187
                    <code-name-base>org.netbeans.modules.xml.core</code-name-base>
196
                    <code-name-base>org.netbeans.modules.xml.core</code-name-base>
188
                    <build-prerequisite/>
197
                    <build-prerequisite/>
189
                    <compile-dependency/>
198
                    <compile-dependency/>
190
                    <run-dependency>
199
                    <run-dependency>
191
                        <release-version>2</release-version>
200
                        <release-version>2</release-version>
192
                        <specification-version>1.14</specification-version>
201
                        <specification-version>1.28</specification-version>
193
                    </run-dependency>
202
                    </run-dependency>
194
                </dependency>
203
                </dependency>
195
                <dependency>
204
                <dependency>
(-)a/xml.text/src/org/netbeans/modules/xml/text/completion/XMLResultItem.java (-8 / +153 lines)
Lines 49-55 Link Here
49
import java.awt.Font;
49
import java.awt.Font;
50
import java.awt.Graphics;
50
import java.awt.Graphics;
51
import java.awt.event.KeyEvent;
51
import java.awt.event.KeyEvent;
52
import java.io.IOException;
53
import java.net.MalformedURLException;
52
import java.net.URL;
54
import java.net.URL;
55
import java.util.logging.Level;
56
import java.util.logging.Logger;
53
import javax.swing.Action;
57
import javax.swing.Action;
54
import javax.swing.text.*;
58
import javax.swing.text.*;
55
import javax.swing.Icon;
59
import javax.swing.Icon;
Lines 57-69 Link Here
57
import org.netbeans.editor.*;
61
import org.netbeans.editor.*;
58
import javax.swing.JLabel;
62
import javax.swing.JLabel;
59
import org.netbeans.api.editor.completion.Completion;
63
import org.netbeans.api.editor.completion.Completion;
64
import org.netbeans.api.queries.FileEncodingQuery;
60
import org.netbeans.modules.xml.api.model.GrammarResult;
65
import org.netbeans.modules.xml.api.model.GrammarResult;
66
import org.netbeans.modules.xml.api.model.DescriptionSource;
61
import org.netbeans.modules.xml.text.api.XMLDefaultTokenContext;
67
import org.netbeans.modules.xml.text.api.XMLDefaultTokenContext;
62
import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport;
68
import org.netbeans.modules.xml.text.syntax.XMLSyntaxSupport;
63
import org.netbeans.spi.editor.completion.CompletionDocumentation;
69
import org.netbeans.spi.editor.completion.CompletionDocumentation;
64
import org.netbeans.spi.editor.completion.CompletionItem;
70
import org.netbeans.spi.editor.completion.CompletionItem;
65
import org.netbeans.spi.editor.completion.CompletionResultSet;
71
import org.netbeans.spi.editor.completion.CompletionResultSet;
66
import org.netbeans.spi.editor.completion.CompletionTask;
72
import org.netbeans.spi.editor.completion.CompletionTask;
73
import org.openide.filesystems.FileObject;
74
import org.openide.filesystems.URLMapper;
75
import org.openide.util.Exceptions;
67
76
68
/**
77
/**
69
 * This class carries result information required by NetBeans Editor module.
78
 * This class carries result information required by NetBeans Editor module.
Lines 72-77 Link Here
72
 * @author  Sandeep Randhawa
81
 * @author  Sandeep Randhawa
73
 */
82
 */
74
class XMLResultItem implements CompletionItem {
83
class XMLResultItem implements CompletionItem {
84
    private static final Logger LOG = Logger.getLogger(XMLResultItem.class.getName());
75
    
85
    
76
    // text to be diplayed to user
86
    // text to be diplayed to user
77
    public final String displayText;
87
    public final String displayText;
Lines 304-328 Link Here
304
    protected CompletionTask doCreateDocumentationTask(final GrammarResult res) {
314
    protected CompletionTask doCreateDocumentationTask(final GrammarResult res) {
305
        return new CompletionTask() {
315
        return new CompletionTask() {
306
            public void query(CompletionResultSet resultSet) {
316
            public void query(CompletionResultSet resultSet) {
307
                if (res != null && res.getDescription() != null) {
317
                CompletionDocumentation cd = create();
308
                    resultSet.setDocumentation(new Docum(res.getDescription()));
318
                if (cd != null) {
309
    
319
                    resultSet.setDocumentation(cd);
310
                }
320
                }
311
                resultSet.finish();
321
                resultSet.finish();
312
            }
322
            }
313
            public void refresh(CompletionResultSet resultSet) {
323
            public void refresh(CompletionResultSet resultSet) {
314
                if (res != null && res.getDescription() != null) {
324
                query(resultSet);
315
                    resultSet.setDocumentation(new Docum(res.getDescription()));
316
                }
317
                resultSet.finish();
318
            }
325
            }
319
            public void cancel() {}
326
            public void cancel() {}
327
328
            
329
            private CompletionDocumentation create() {
330
                String doc;
331
                
332
                doc = res.getDescription();
333
                if (!(res instanceof DescriptionSource)) {
334
                    if (doc == null) {
335
                        return null;
336
                    }
337
                    return new Docum(doc);
338
                } else {
339
                    DescriptionSource ds = (DescriptionSource)res;
340
                    if (doc == null && ds.getContentURL() == null) {
341
                        return null;
342
                    }
343
                    return new ExtDocum(ds,  doc);
344
                }
345
            }
320
        };
346
        };
321
    }
347
    }
348
349
    /**
350
     * Extended documentation, based on the {@link DescriptionSource} SPI.
351
     */
352
    private static class ExtDocum extends URLDocum implements CompletionDocumentation {
353
        private DescriptionSource src;
354
        private String doc;
355
356
        ExtDocum(DescriptionSource src, String doc) {
357
            super(src.getContentURL(), src.isExternal());
358
            this.src = src;
359
            this.doc = doc;
360
        }
361
362
        @Override
363
        public String getText() {
364
            if (doc == null) {
365
                doc = src.getDescription();
366
                if (doc == null) {
367
                    doc = super.getText();
368
                }
369
            }
370
            return doc;
371
        }
372
373
        @Override
374
        public CompletionDocumentation resolveLink(String link) {
375
            try {
376
                DescriptionSource target = src.resolveLink(link);
377
                if (target != null) {
378
                    return new ExtDocum(target, null);
379
                }
380
                
381
                URL base = src.getContentURL();
382
                if (base == null) {
383
                    // sorry, cannot resolve.
384
                    return null;
385
                }
386
                
387
                URL targetURL = new URL(base, link);
388
                
389
                // leave the VM as soon as possible. This hack uses URLMappers
390
                // to find out whether URL (converted to FO and back) can be
391
                // represented outside the VM
392
                boolean external = true;
393
                FileObject f = URLMapper.findFileObject(targetURL);
394
                if (f != null) {
395
                    external = URLMapper.findURL(f, URLMapper.EXTERNAL) != null;
396
                }
397
                return new URLDocum(targetURL, external);
398
            } catch (MalformedURLException ex) {
399
                Exceptions.printStackTrace(ex);
400
                return null;
401
            }
402
        }
403
404
        @Override
405
        public Action getGotoSourceAction() {
406
            return null;
407
        }
408
    }
409
    
410
    /**
411
     * Pure URL documentation item. Resolves links, if original URL was able
412
     * to open externally, the derived URLs do it as well.
413
     */
414
    private static class URLDocum implements CompletionDocumentation {
415
        URL content;
416
        boolean external;
417
        
418
        URLDocum(URL content, boolean external) {
419
            this.content = content;
420
            this.external = external;
421
        }
422
        
423
        URLDocum(boolean external) {
424
            this.external = external;
425
        }
426
427
        @Override
428
        public Action getGotoSourceAction() {
429
            return null;
430
        }
431
432
        @Override
433
        public String getText() {
434
            if (content == null) {
435
                return null;
436
            }
437
            FileObject f = URLMapper.findFileObject(content);
438
            if (f != null) {
439
                try {
440
                    return new String(f.asBytes(), FileEncodingQuery.getEncoding(f));
441
                } catch (IOException x) {
442
                    LOG.log(Level.INFO, "Could not load " + content, x);
443
                }
444
            }
445
            return null;
446
        }
447
448
        @Override
449
        public URL getURL() {
450
            return external ? content : null;
451
        }
452
453
        @Override
454
        public CompletionDocumentation resolveLink(String link) {
455
            if (content == null) {
456
                return null;
457
            }
458
            try {
459
                return new URLDocum(new URL(content, link), external);
460
            } catch (MalformedURLException ex) {
461
                Exceptions.printStackTrace(ex);
462
                return null;
463
            }
464
        }
465
        
466
    }
322
    
467
    
323
    private static class Docum implements CompletionDocumentation {
468
    private static class Docum implements CompletionDocumentation {
324
        private String doc;
469
        private String doc;
325
470
        
326
        private Docum(String doc) {
471
        private Docum(String doc) {
327
            this.doc = doc;
472
            this.doc = doc;
328
        }
473
        }
(-)a/xml.text/test/unit/src/org/netbeans/modules/xml/text/completion/ElementResultItemDocumentationTest.java (+382 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2011 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.xml.text.completion;
43
44
import java.lang.reflect.Constructor;
45
import java.net.URL;
46
import javax.swing.Icon;
47
import org.netbeans.junit.NbTestCase;
48
import org.netbeans.junit.NbTestSuite;
49
50
import org.netbeans.modules.editor.completion.CompletionImpl;
51
import org.netbeans.modules.editor.completion.CompletionResultSetImpl;
52
import org.netbeans.modules.xml.api.EncodingUtil;
53
import org.netbeans.modules.xml.api.model.DescriptionSource;
54
import org.netbeans.modules.xml.api.model.GrammarResult;
55
import org.netbeans.modules.xml.spi.dom.AbstractNode;
56
import org.netbeans.spi.editor.completion.CompletionDocumentation;
57
import org.netbeans.spi.editor.completion.CompletionProvider;
58
import org.netbeans.spi.editor.completion.CompletionResultSet;
59
import org.netbeans.spi.editor.completion.CompletionTask;
60
61
/**
62
 * Checks behaviour of {@link GrammarResult} support in the ElementResultItem.
63
 * plain CompletionDocumentation must work unchanged. If mixin interface is implemented,
64
 * explicit values (content, resolved links) must take precedence.
65
 * <p/>
66
 * If contentURL is provided, links must be resolved and content loaded by the 
67
 * ElementResultItem support even though the supplied CompletionDocumentation itself does not 
68
 * provide content/links.
69
 * 
70
 * @author sdedic
71
 */
72
public class ElementResultItemDocumentationTest extends NbTestCase {
73
74
    public static NbTestSuite suite() {
75
        NbTestSuite suite = new NbTestSuite();
76
        suite.addTestSuite(ElementResultItemDocumentationTest.class);
77
        return suite;
78
    }
79
80
    public ElementResultItemDocumentationTest(String name) {
81
        super(name);
82
    }
83
84
    @Override
85
    protected void setUp() throws Exception {
86
        super.setUp();
87
    }
88
89
    @Override
90
    protected void tearDown() throws Exception {
91
        super.tearDown();
92
    }
93
    
94
    private CompletionResultSetImpl rsImpl;
95
    
96
    
97
    private CompletionResultSet resultSetFor(CompletionTask task, int type) throws Exception {
98
        rsImpl = createCompletionResultImpl(task, type);
99
        return rsImpl.getResultSet();
100
    }
101
    
102
    private CompletionResultSetImpl createCompletionResultImpl(CompletionTask task, int type) throws Exception {
103
        Class clazz = CompletionResultSetImpl.class;
104
        Constructor ctor = clazz.getDeclaredConstructor(CompletionImpl.class, Object.class, CompletionTask.class, Integer.TYPE);
105
        ctor.setAccessible(true);
106
        return (CompletionResultSetImpl)ctor.newInstance(CompletionImpl.get(), "", task, type);
107
    }
108
    
109
    /**
110
     * Check the previou state, result items without the mixin interface. 
111
     * Should return the description 'as is'
112
     * 
113
     * @throws Exception 
114
     */
115
    private static final String PLAIN_DESCRIPTION_TEXT = "Plain description";
116
    
117
    public void testPlainContent() throws Exception {
118
        MockGrammarResult r = new MockGrammarResult();
119
        
120
        r.setDescription(PLAIN_DESCRIPTION_TEXT);
121
        ElementResultItem item = new ElementResultItem(0, r);
122
        CompletionTask task = item.doCreateDocumentationTask(r);
123
124
        CompletionResultSet rs = resultSetFor(task, CompletionProvider.DOCUMENTATION_QUERY_TYPE);
125
        task.query(rs);
126
        
127
        assertTrue(rs.isFinished());
128
        
129
        assertEquals(PLAIN_DESCRIPTION_TEXT, rsImpl.getDocumentation().getText());
130
     
131
        // should return null from the url.
132
        assertNull(rsImpl.getDocumentation().getURL());
133
        
134
        // should not be able to resolve links
135
        assertNull(rsImpl.getDocumentation().resolveLink("link"));
136
    }
137
    
138
    private URL  createResourceName(String n) {
139
        return ElementResultItemDocumentationTest.class.getResource(n);
140
    }
141
    
142
    private CompletionDocumentation createDocResourceResultSet(MockUrlGrammarResult r) throws Exception {
143
        if (r == null) {
144
            r = new MockUrlGrammarResult();
145
            r.setContentURL(createResourceName("res/docResource.html"));
146
            r.setExternal(true);
147
        }
148
        
149
        ElementResultItem item = new ElementResultItem(0, r);
150
        CompletionTask task = item.doCreateDocumentationTask(r);
151
        CompletionResultSet rs = resultSetFor(task, CompletionProvider.DOCUMENTATION_QUERY_TYPE);
152
        task.query(rs);
153
154
        assertTrue(rs.isFinished());
155
        
156
        return rsImpl.getDocumentation();
157
    }
158
    
159
    /**
160
     * Checks that custom contents overrides the one supplied by XMLResultItem
161
     * 
162
     * @throws Exception 
163
     */
164
    public void testCustomContent() throws Exception {
165
        URL res = EncodingUtil.class.getResource("/org/netbeans/modules/xml/core/resources/Bundle.properties");
166
        MockUrlGrammarResult test = new MockUrlGrammarResult();
167
        test.setContentURL(res);
168
        test.setExternal(false);
169
        test.setDescription(PLAIN_DESCRIPTION_TEXT);
170
        
171
        CompletionDocumentation doc = createDocResourceResultSet(test);
172
        assertNull(doc.getURL());
173
        assertEquals("Invalid content", PLAIN_DESCRIPTION_TEXT, doc.getText());
174
    }
175
176
    /**
177
     * Checks documentation bundled in a JAR - not openable by external browser.
178
     * Need a resource within a JAR
179
     * 
180
     * @throws Exception 
181
     */
182
    public void testInternalUrlDocumentation() throws Exception {
183
        URL res = EncodingUtil.class.getResource("/org/netbeans/modules/xml/core/resources/Bundle.properties");
184
        MockUrlGrammarResult test = new MockUrlGrammarResult();
185
        test.setContentURL(res);
186
        test.setExternal(false);
187
        
188
        CompletionDocumentation doc = createDocResourceResultSet(test);
189
        assertNull(doc.getURL());
190
        assertTrue(doc.getText().contains("OpenIDE-Module-Name=XML Core"));
191
        
192
        // check that relative links still resolve to internal doc
193
        CompletionDocumentation  internal = doc.resolveLink("mf-layer.xml");
194
        assertNotNull("Relative links must be resolvable", internal);
195
        assertNull("Relative links cannot be opened in extbrowser", doc.getURL());
196
        assertTrue("Content must be accessible", 
197
                internal.getText().contains("org-netbeans-modules-xml-dtd-grammar-DTDGrammarQueryProvider.instance"));
198
        
199
        // check that absolute links resolve to external doc
200
        CompletionDocumentation  external = doc.resolveLink("http://www.netbeans.org");
201
        assertNotNull("Absolute links must be resolvable", external);
202
        assertEquals("Absolute links must have URL", external.getURL(), new URL("http://www.netbeans.org"));
203
    }
204
    
205
    /**
206
     * Checks that file-based documentation reverts to external as soon as possible
207
     * @throws Exception 
208
     */
209
    public void testFileDocumentation() throws Exception {
210
        URL res = EncodingUtil.class.getResource("/org/netbeans/modules/xml/core/resources/Bundle.properties");
211
        MockUrlGrammarResult test = new MockUrlGrammarResult();
212
        test.setContentURL(res);
213
        test.setExternal(false);
214
215
        CompletionDocumentation doc = createDocResourceResultSet(test);
216
        assertNull(doc.getURL());
217
        assertTrue("Invalid content", doc.getText().contains("OpenIDE-Module-Name=XML Core"));
218
        
219
        // check that resolve of file-based URL turns the doc to external:
220
221
        URL url = createResourceName("res/docResource.html");
222
        CompletionDocumentation  file = doc.resolveLink(url.toString());
223
        assertNotNull(file);
224
        assertEquals("URL must be openable in browser", url, file.getURL());
225
        assertTrue("Invalid content of the linked doc", file.getText().startsWith("This is an URL resource with <a href="));
226
    }
227
    
228
    /**
229
     * Checks that relative and .. link resolution works OK.
230
     * 
231
     * @throws Exception 
232
     */
233
    public void testResolveRelativeLinks() throws Exception {
234
        CompletionDocumentation doc = createDocResourceResultSet(null);
235
                
236
        assertEquals(createResourceName("res/docResource.html"), doc.getURL());
237
        
238
        CompletionDocumentation linked = doc.resolveLink("relativeLink1.html");
239
        assertNotNull(linked);
240
        assertEquals("Relative link must be resolved", createResourceName("res/relativeLink1.html"), linked.getURL());
241
        
242
        linked = doc.resolveLink("../parentDoc.html");
243
        assertNotNull(linked);
244
        assertEquals("Link to resource in parent folder must be resolved", createResourceName("parentDoc.html"), linked.getURL());
245
    }
246
    
247
    /**
248
     * Checks that DS returning 'external' provides URL and resolves links, although
249
     * no custom resolver is given
250
     * 
251
     * @throws Exception 
252
     */
253
    public void testNetworkUrlDocumentation() throws Exception {
254
        MockUrlGrammarResult test = new MockUrlGrammarResult();
255
        test.setExternal(true);
256
        test.setContentURL(new URL("http://www.netbeans.org"));
257
        
258
        CompletionDocumentation doc = createDocResourceResultSet(test);
259
        assertEquals("External documentation must have URL", new URL("http://www.netbeans.org"), doc.getURL());
260
        
261
        CompletionDocumentation resolved = doc.resolveLink("index.html");
262
        assertEquals("Resolved external link must have URL", new URL("http://www.netbeans.org/index.html"), resolved.getURL());
263
    }
264
    
265
    /**
266
     * Checks that without content URL, no item is produced
267
     * @throws Exception 
268
     */
269
    public void testNoContentUrl() throws Exception {
270
        MockUrlGrammarResult res = new MockUrlGrammarResult();
271
        CompletionDocumentation doc = createDocResourceResultSet(res);
272
        
273
        assertNull(doc);
274
    }
275
    
276
    public void testCustomResolveLink() throws Exception {
277
        MockUrlGrammarResult res = new MockUrlGrammarResult() {
278
279
            // resolves relative links in different directory
280
            @Override
281
            public DescriptionSource resolveLink(String link) {
282
                MockUrlGrammarResult res = new MockUrlGrammarResult();
283
                URL base = createResourceName("res/" + link);
284
                res.setContentURL(base);
285
                res.setExternal(link.contains("Exist.html"));
286
                if (link.contains("customContent")) {
287
                    res.setDescription(PLAIN_DESCRIPTION_TEXT);
288
                }
289
                return res;
290
            }
291
        };
292
        res.setContentURL(createResourceName("res/docResource.html"));
293
        CompletionDocumentation doc = createDocResourceResultSet(res);
294
        
295
        // doc does not exist, but documentation item is there
296
        CompletionDocumentation notExisting = doc.resolveLink("doesNotExist.html");
297
        assertNotNull(notExisting);
298
        //  it is external, as defined by custom resolver
299
        assertEquals(createResourceName("doesNotExist.html"), notExisting.getURL());
300
        // but contents cannot be fetched by the framework
301
        assertNull("Supplied description must take precedence", notExisting.getText());
302
303
        // existing item
304
        CompletionDocumentation resolved = doc.resolveLink("relativeLink1.html");
305
        // custom resolver says this is an internal link!
306
        assertNull("Must not be openable in browser", resolved.getURL());
307
        // fwk is able to fetch contents
308
        assertTrue("Framework must fetch contents of linked URL", 
309
                resolved.getText().startsWith("Resource referenced by relative link"));
310
        
311
        CompletionDocumentation parent = doc.resolveLink("customContent");
312
        assertEquals(PLAIN_DESCRIPTION_TEXT, parent.getText());
313
    }
314
    
315
    private static class MockUrlGrammarResult extends MockGrammarResult implements DescriptionSource {
316
        private URL contentURL;
317
        private boolean external;
318
319
        public void setContentURL(URL contentURL) {
320
            this.contentURL = contentURL;
321
        }
322
323
        public void setExternal(boolean external) {
324
            this.external = external;
325
        }
326
        
327
        @Override
328
        public URL getContentURL() {
329
            return contentURL;
330
        }
331
332
        @Override
333
        public boolean isExternal() {
334
            return external;
335
        }
336
337
        @Override
338
        public DescriptionSource resolveLink(String link) {
339
            return null;
340
        }
341
        
342
    }
343
    
344
    private static class MockGrammarResult extends AbstractNode implements GrammarResult {
345
        private String description;
346
        private String displayName;
347
348
        public void setDescription(String description) {
349
            this.description = description;
350
        }
351
352
        public void setDisplayName(String displayName) {
353
            this.displayName = displayName;
354
        }
355
        
356
        @Override
357
        public String getDescription() {
358
            return description;
359
        }
360
361
        @Override
362
        public String getDisplayName() {
363
            return displayName;
364
        }
365
366
        @Override
367
        public Icon getIcon(int kind) {
368
            return null;
369
        }
370
371
        @Override
372
        public boolean isEmptyElement() {
373
            return false;
374
        }
375
376
        @Override
377
        public short getNodeType() {
378
            return ELEMENT_NODE;
379
        }
380
        
381
    }
382
}
(-)a/xml.text/test/unit/src/org/netbeans/modules/xml/text/completion/parentDoc.html (+1 lines)
Line 0 Link Here
1
Document in parent directory
(-)a/xml.text/test/unit/src/org/netbeans/modules/xml/text/completion/res/docResource.html (+2 lines)
Line 0 Link Here
1
This is an URL resource with <a href="relativeLink1.html">relative link</a> and
2
<a href="http://www.seznam.cz">absolute link</a>
(-)a/xml.text/test/unit/src/org/netbeans/modules/xml/text/completion/res/relativeLink1.html (+1 lines)
Line 0 Link Here
1
Resource referenced by relative link

Return to bug 199742