Source Code Cross Referenced for XMLContentAssistProcessor.java in  » IDE-Eclipse » Eclipse-plug-in-development » org » eclipse » pde » internal » ui » editor » contentassist » 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 Eclipse » Eclipse plug in development » org.eclipse.pde.internal.ui.editor.contentassist 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2006, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Remy Chi Jian Suen <remy.suen@gmail.com> - bug 201566
0011:         *******************************************************************************/package org.eclipse.pde.internal.ui.editor.contentassist;
0012:
0013:        import java.util.ArrayList;
0014:        import java.util.Iterator;
0015:        import java.util.TreeSet;
0016:        import java.util.regex.Pattern;
0017:
0018:        import org.eclipse.core.resources.IResource;
0019:        import org.eclipse.jdt.core.search.IJavaSearchConstants;
0020:        import org.eclipse.jface.text.BadLocationException;
0021:        import org.eclipse.jface.text.IDocument;
0022:        import org.eclipse.jface.text.ITextSelection;
0023:        import org.eclipse.jface.text.ITextViewer;
0024:        import org.eclipse.jface.text.contentassist.ContentAssistEvent;
0025:        import org.eclipse.jface.text.contentassist.ICompletionListener;
0026:        import org.eclipse.jface.text.contentassist.ICompletionProposal;
0027:        import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
0028:        import org.eclipse.jface.viewers.ISelection;
0029:        import org.eclipse.pde.core.IBaseModel;
0030:        import org.eclipse.pde.core.IIdentifiable;
0031:        import org.eclipse.pde.core.plugin.IPluginBase;
0032:        import org.eclipse.pde.core.plugin.IPluginExtension;
0033:        import org.eclipse.pde.core.plugin.IPluginExtensionPoint;
0034:        import org.eclipse.pde.core.plugin.IPluginModelBase;
0035:        import org.eclipse.pde.core.plugin.IPluginObject;
0036:        import org.eclipse.pde.core.plugin.PluginRegistry;
0037:        import org.eclipse.pde.internal.core.ischema.IMetaAttribute;
0038:        import org.eclipse.pde.internal.core.ischema.ISchemaAttribute;
0039:        import org.eclipse.pde.internal.core.ischema.ISchemaComplexType;
0040:        import org.eclipse.pde.internal.core.ischema.ISchemaCompositor;
0041:        import org.eclipse.pde.internal.core.ischema.ISchemaElement;
0042:        import org.eclipse.pde.internal.core.ischema.ISchemaObject;
0043:        import org.eclipse.pde.internal.core.ischema.ISchemaRestriction;
0044:        import org.eclipse.pde.internal.core.ischema.ISchemaSimpleType;
0045:        import org.eclipse.pde.internal.core.text.AbstractEditingModel;
0046:        import org.eclipse.pde.internal.core.text.IDocumentAttributeNode;
0047:        import org.eclipse.pde.internal.core.text.IDocumentElementNode;
0048:        import org.eclipse.pde.internal.core.text.IDocumentRange;
0049:        import org.eclipse.pde.internal.core.text.IDocumentTextNode;
0050:        import org.eclipse.pde.internal.core.text.IReconcilingParticipant;
0051:        import org.eclipse.pde.internal.core.text.plugin.PluginModelBase;
0052:        import org.eclipse.pde.internal.core.util.IdUtil;
0053:        import org.eclipse.pde.internal.ui.PDEPluginImages;
0054:        import org.eclipse.pde.internal.ui.PDEUIMessages;
0055:        import org.eclipse.pde.internal.ui.editor.PDEFormEditor;
0056:        import org.eclipse.pde.internal.ui.editor.PDESourcePage;
0057:        import org.eclipse.pde.internal.ui.editor.text.XMLUtil;
0058:        import org.eclipse.swt.graphics.Image;
0059:        import org.eclipse.ui.forms.editor.FormEditor;
0060:
0061:        public class XMLContentAssistProcessor extends
0062:                TypePackageCompletionProcessor implements 
0063:                IContentAssistProcessor, ICompletionListener {
0064:
0065:            protected boolean fAssistSessionStarted;
0066:
0067:            // Specific assist types
0068:
0069:            protected static final int F_INFER_BY_OBJECT = -1;
0070:
0071:            protected static final int F_EXTENSION_POINT = 0;
0072:
0073:            protected static final int F_EXTENSION = 1;
0074:
0075:            protected static final int F_ELEMENT = 2;
0076:
0077:            protected static final int F_ATTRIBUTE = 3;
0078:
0079:            protected static final int F_CLOSE_TAG = 4;
0080:
0081:            protected static final int F_ATTRIBUTE_VALUE = 5;
0082:
0083:            protected static final int F_EXTENSION_ATTRIBUTE_POINT_VALUE = 6;
0084:
0085:            protected static final int F_EXTENSION_POINT_AND_VALUE = 7;
0086:
0087:            protected static final int F_TOTAL_TYPES = 8;
0088:
0089:            // proposal generation type
0090:            private static final int F_NO_ASSIST = 0, F_ADD_ATTRIB = 1,
0091:                    F_ADD_CHILD = 2, F_OPEN_TAG = 3;
0092:
0093:            private static final ArrayList F_V_BOOLS = new ArrayList();
0094:            static {
0095:                F_V_BOOLS.add(new VirtualSchemaObject(
0096:                        "true", null, F_ATTRIBUTE_VALUE)); //$NON-NLS-1$
0097:                F_V_BOOLS.add(new VirtualSchemaObject(
0098:                        "false", null, F_ATTRIBUTE_VALUE)); //$NON-NLS-1$
0099:            }
0100:
0101:            private static final String F_STR_EXT_PT = "extension-point"; //$NON-NLS-1$
0102:            private static final String F_STR_EXT = "extension"; //$NON-NLS-1$
0103:
0104:            private PDESourcePage fSourcePage;
0105:            private final Image[] fImages = new Image[F_TOTAL_TYPES];
0106:            // TODO add a listener to add/remove extension points as they are added/removed from working models
0107:            private IDocumentRange fRange;
0108:            private int fDocLen = -1;
0109:
0110:            /** All external plug-in extension points */
0111:            private ArrayList fExternalExtPoints;
0112:
0113:            /** All internal plug-in extension points */
0114:            private ArrayList fInternalExtPoints;
0115:
0116:            /** All external and internal plug-in extension points */
0117:            private ArrayList fAllExtPoints;
0118:
0119:            public XMLContentAssistProcessor(PDESourcePage sourcePage) {
0120:                fSourcePage = sourcePage;
0121:            }
0122:
0123:            public ICompletionProposal[] computeCompletionProposals(
0124:                    ITextViewer viewer, int offset) {
0125:                IDocument doc = viewer.getDocument();
0126:                int docLen = doc.getLength();
0127:                if (docLen == fDocLen)
0128:                    return null; // left/right cursor has been pressed - cancel content assist
0129:
0130:                fDocLen = docLen;
0131:                IBaseModel model = getModel();
0132:                if (model instanceof  AbstractEditingModel
0133:                        && fSourcePage.isDirty()
0134:                        && ((AbstractEditingModel) model).isStale()
0135:                        && fRange == null) {
0136:                    ((AbstractEditingModel) model).reconciled(doc);
0137:                } else if (fAssistSessionStarted) {
0138:                    // Always reconcile when content assist is first invoked
0139:                    // Fix Bug # 149478
0140:                    ((AbstractEditingModel) model).reconciled(doc);
0141:                    fAssistSessionStarted = false;
0142:                }
0143:
0144:                if (fRange == null) {
0145:                    assignRange(offset);
0146:                } else {
0147:                    // TODO - we may be looking at the wrong fRange
0148:                    // when this happens --> reset it and reconcile
0149:                    // how can we tell if we are looking at the wrong one... ?
0150:                    boolean resetAndReconcile = false;
0151:                    if (!(fRange instanceof  IDocumentAttributeNode))
0152:                        // too easy to reconcile.. this is temporary
0153:                        resetAndReconcile = true;
0154:
0155:                    if (resetAndReconcile) {
0156:                        fRange = null;
0157:                        if (model instanceof  IReconcilingParticipant)
0158:                            ((IReconcilingParticipant) model).reconciled(doc);
0159:                    }
0160:                }
0161:                // Get content assist text if any
0162:                XMLContentAssistText caText = XMLContentAssistText.parse(
0163:                        offset, doc);
0164:
0165:                if (caText != null) {
0166:                    return computeCATextProposal(doc, offset, caText);
0167:                } else if (fRange instanceof  IDocumentAttributeNode) {
0168:                    return computeCompletionProposal(
0169:                            (IDocumentAttributeNode) fRange, offset, doc);
0170:                } else if (fRange instanceof  IDocumentElementNode) {
0171:                    return computeCompletionProposal(
0172:                            (IDocumentElementNode) fRange, offset, doc);
0173:                } else if (fRange instanceof  IDocumentTextNode) {
0174:                    return null;
0175:                } else if (model instanceof  PluginModelBase) {
0176:                    // broken model - infer from text content
0177:                    return computeBrokenModelProposal(((PluginModelBase) model)
0178:                            .getLastErrorNode(), offset, doc);
0179:                }
0180:                return null;
0181:            }
0182:
0183:            /**
0184:             * @param proposals
0185:             * @param id
0186:             * @param print
0187:             * @return
0188:             */
0189:            protected ICompletionProposal[] debugPrintProposals(
0190:                    ICompletionProposal[] proposals, String id, boolean print) {
0191:                if (proposals == null) {
0192:                    System.out.println("[0] " + id); //$NON-NLS-1$
0193:                    return proposals;
0194:                }
0195:                System.out.println("[" + proposals.length + "] " + id); //$NON-NLS-1$ //$NON-NLS-2$
0196:                if (print == false) {
0197:                    return proposals;
0198:                }
0199:                for (int i = 0; i < proposals.length; i++) {
0200:                    System.out.println(proposals[i].getDisplayString());
0201:                }
0202:                return proposals;
0203:            }
0204:
0205:            private void assignRange(int offset) {
0206:                fRange = fSourcePage.getRangeElement(offset, true);
0207:                if (fRange == null)
0208:                    return;
0209:                // if we are rigth AT (cursor before) the range, we want to contribute
0210:                // to its parent
0211:                if (fRange instanceof  IDocumentAttributeNode) {
0212:                    if (((IDocumentAttributeNode) fRange).getNameOffset() == offset)
0213:                        fRange = ((IDocumentAttributeNode) fRange)
0214:                                .getEnclosingElement();
0215:                } else if (fRange instanceof  IDocumentElementNode) {
0216:                    if (((IDocumentElementNode) fRange).getOffset() == offset)
0217:                        fRange = ((IDocumentElementNode) fRange)
0218:                                .getParentNode();
0219:                } else if (fRange instanceof  IDocumentTextNode) {
0220:                    if (((IDocumentTextNode) fRange).getOffset() == offset)
0221:                        fRange = ((IDocumentTextNode) fRange)
0222:                                .getEnclosingElement();
0223:                }
0224:            }
0225:
0226:            private ICompletionProposal[] computeCATextProposal(IDocument doc,
0227:                    int offset, XMLContentAssistText caText) {
0228:                fRange = fSourcePage.getRangeElement(offset, true);
0229:                if ((fRange != null) && (fRange instanceof  IDocumentTextNode)) {
0230:                    // We have a text node.
0231:                    // Get its parent element
0232:                    fRange = ((IDocumentTextNode) fRange).getEnclosingElement();
0233:                }
0234:                if ((fRange != null)
0235:                        && (fRange instanceof  IDocumentElementNode)) {
0236:                    return computeAddChildProposal(
0237:                            (IDocumentElementNode) fRange, caText
0238:                                    .getStartOffset(), doc, caText.getText());
0239:                }
0240:                return null;
0241:            }
0242:
0243:            private ICompletionProposal[] computeCompletionProposal(
0244:                    IDocumentAttributeNode attr, int offset, IDocument doc) {
0245:                if (offset < attr.getValueOffset())
0246:                    return null;
0247:                int[] offests = new int[] { offset, offset, offset };
0248:                String[] guess = guessContentRequest(offests, doc, false);
0249:                if (guess == null)
0250:                    return null;
0251:                //		String element = guess[0];
0252:                //		String attribute = guess[1];
0253:                String attrValue = guess[2];
0254:
0255:                IPluginObject obj = XMLUtil.getTopLevelParent(attr);
0256:                if (obj instanceof  IPluginExtension) {
0257:                    if (attr.getAttributeName()
0258:                            .equals(IPluginExtension.P_POINT)
0259:                            && offset >= attr.getValueOffset()) {
0260:                        return computeExtPointAttrProposals(attr, offset,
0261:                                attrValue);
0262:                    }
0263:                    ISchemaAttribute sAttr = XMLUtil.getSchemaAttribute(attr,
0264:                            ((IPluginExtension) obj).getPoint());
0265:                    if (sAttr == null)
0266:                        return null;
0267:
0268:                    if (sAttr.getKind() == IMetaAttribute.JAVA) {
0269:                        IResource resource = obj.getModel()
0270:                                .getUnderlyingResource();
0271:                        if (resource == null)
0272:                            return null;
0273:                        // Revisit: NEW CODE HERE
0274:                        ArrayList list = new ArrayList();
0275:                        ICompletionProposal[] proposals = null;
0276:
0277:                        generateTypePackageProposals(attrValue, resource
0278:                                .getProject(), list, offset
0279:                                - attrValue.length(),
0280:                                IJavaSearchConstants.CLASS_AND_INTERFACE);
0281:
0282:                        if ((list != null) && (list.size() != 0)) {
0283:                            // Convert the results array list into an array of completion
0284:                            // proposals
0285:                            proposals = (ICompletionProposal[]) list
0286:                                    .toArray(new ICompletionProposal[list
0287:                                            .size()]);
0288:                            sortCompletions(proposals);
0289:                            return proposals;
0290:                        }
0291:                        return null;
0292:                    } else if (sAttr.getKind() == IMetaAttribute.RESOURCE) {
0293:                        // provide proposals with all resources in current plugin?
0294:
0295:                    } else { // we have an IMetaAttribute.STRING kind
0296:                        if (sAttr.getType() == null)
0297:                            return null;
0298:                        ISchemaRestriction sRestr = (sAttr.getType())
0299:                                .getRestriction();
0300:                        ArrayList objs = new ArrayList();
0301:                        if (sRestr == null) {
0302:                            ISchemaSimpleType type = sAttr.getType();
0303:                            if (type != null
0304:                                    && type.getName().equals("boolean")) //$NON-NLS-1$
0305:                                objs = F_V_BOOLS;
0306:                        } else {
0307:                            Object[] restrictions = sRestr.getChildren();
0308:                            for (int i = 0; i < restrictions.length; i++)
0309:                                if (restrictions[i] instanceof  ISchemaObject)
0310:                                    objs.add(new VirtualSchemaObject(
0311:                                            ((ISchemaObject) restrictions[i])
0312:                                                    .getName(), null,
0313:                                            F_ATTRIBUTE_VALUE));
0314:                        }
0315:                        return computeAttributeProposal(attr, offset,
0316:                                attrValue, objs);
0317:                    }
0318:                } else if (obj instanceof  IPluginExtensionPoint) {
0319:                    if (attr.getAttributeValue().equals(
0320:                            IPluginExtensionPoint.P_SCHEMA)) {
0321:                        // provide proposals with all schama files in current plugin?
0322:
0323:                    }
0324:                }
0325:                return null;
0326:            }
0327:
0328:            /**
0329:             * @param attribute
0330:             * @param offset
0331:             * @param currentAttributeValue
0332:             * @return
0333:             */
0334:            private ICompletionProposal[] computeExtPointAttrProposals(
0335:                    IDocumentAttributeNode attribute, int offset,
0336:                    String currentAttributeValue) {
0337:                // Get all the applicable extension points
0338:                ArrayList allExtensionPoints = getAllExtensionPoints(F_EXTENSION_ATTRIBUTE_POINT_VALUE);
0339:                // Ensure we found extension points
0340:                if ((allExtensionPoints == null)
0341:                        || (allExtensionPoints.size() == 0)) {
0342:                    return null;
0343:                }
0344:                // If there is no current attribute value, then the applicable extension
0345:                // points do not need to be filtered.  Return the list as is
0346:                if ((currentAttributeValue == null)
0347:                        || (currentAttributeValue.length() == 0)) {
0348:                    return convertListToProposal(allExtensionPoints, attribute,
0349:                            offset);
0350:                }
0351:                // Create the filtered proposal list
0352:                ArrayList filteredProposalList = new ArrayList();
0353:                // Filter the applicable extension points by the current attribute
0354:                // value
0355:                filterExtPointAttrProposals(filteredProposalList,
0356:                        allExtensionPoints, currentAttributeValue);
0357:                // Convert into a digestable list of proposals
0358:                return convertListToProposal(filteredProposalList, attribute,
0359:                        offset);
0360:            }
0361:
0362:            /**
0363:             * @param node
0364:             * @param offset
0365:             * @param filter
0366:             * @return
0367:             */
0368:            private ICompletionProposal[] computeRootNodeProposals(
0369:                    IDocumentElementNode node, int offset, String filter) {
0370:                // Create the filtered proposal list
0371:                ArrayList filteredProposalList = new ArrayList();
0372:                // Add extension to the list
0373:                addToList(
0374:                        filteredProposalList,
0375:                        filter,
0376:                        new VirtualSchemaObject(
0377:                                F_STR_EXT,
0378:                                PDEUIMessages.XMLContentAssistProcessor_extensions,
0379:                                F_EXTENSION));
0380:                // Add extension point to the list
0381:                addToList(
0382:                        filteredProposalList,
0383:                        filter,
0384:                        new VirtualSchemaObject(
0385:                                F_STR_EXT_PT,
0386:                                PDEUIMessages.XMLContentAssistProcessor_extensionPoints,
0387:                                F_EXTENSION_POINT));
0388:                // Get all avaliable extensions with point attribute values
0389:                ArrayList allExtensionPoints = getAllExtensionPoints(F_EXTENSION_POINT_AND_VALUE);
0390:                // Ensure we found extension points
0391:                if ((allExtensionPoints == null)
0392:                        || (allExtensionPoints.size() == 0)) {
0393:                    // Return the current proposal list without extension points
0394:                    return convertListToProposal(filteredProposalList, node,
0395:                            offset);
0396:                }
0397:                // If there is no current value, then the applicable extension
0398:                // points do not need to be filtered.  Merge the list as is with the
0399:                // existing proposals
0400:                if ((filter == null) || (filter.length() == 0)) {
0401:                    filteredProposalList.addAll(allExtensionPoints);
0402:                    return convertListToProposal(filteredProposalList, node,
0403:                            offset);
0404:                }
0405:                // Filter the applicable extension points by the current value
0406:                filterExtPointAttrProposals(filteredProposalList,
0407:                        allExtensionPoints, filter);
0408:                // Convert into a digestable list of proposals
0409:                return convertListToProposal(filteredProposalList, node, offset);
0410:            }
0411:
0412:            /**
0413:             * @param filteredProposalList - Must not be NULL
0414:             * @param allExtensionPoints - Must not be NULL
0415:             * @param filter - Must not be NULL
0416:             */
0417:            private void filterExtPointAttrProposals(
0418:                    ArrayList filteredProposalList,
0419:                    ArrayList allExtensionPoints, String filter) {
0420:                // Create a regex pattern out of the current attribute value
0421:                // Ignore case
0422:                String patternString = "(?i)" + filter; //$NON-NLS-1$
0423:                // Compile the pattern
0424:                Pattern pattern = Pattern.compile(patternString);
0425:                // Iterate over the applicable extension points and add extension points
0426:                // matching the pattern to the filtered proposal list
0427:                Iterator iterator = allExtensionPoints.iterator();
0428:                while (iterator.hasNext()) {
0429:                    // Get the schema object
0430:                    ISchemaObject schemaObject = (ISchemaObject) iterator
0431:                            .next();
0432:                    // Ensure the schema object is defined
0433:                    if (schemaObject == null) {
0434:                        continue;
0435:                    }
0436:                    // Get the name of the schema object
0437:                    String name = schemaObject.getName();
0438:                    // If the current attribute value matches some part of the name
0439:                    // add it to the list
0440:                    if (pattern.matcher(name).find()) {
0441:                        filteredProposalList.add(schemaObject);
0442:                    }
0443:                }
0444:            }
0445:
0446:            private ICompletionProposal[] computeAttributeProposal(
0447:                    IDocumentAttributeNode attr, int offset, String currValue,
0448:                    ArrayList validValues) {
0449:                if (validValues == null)
0450:                    return null;
0451:                ArrayList list = new ArrayList();
0452:                for (int i = 0; i < validValues.size(); i++)
0453:                    addToList(list, currValue, (ISchemaObject) validValues
0454:                            .get(i));
0455:
0456:                return convertListToProposal(list, attr, offset);
0457:            }
0458:
0459:            private ICompletionProposal[] computeCompletionProposal(
0460:                    IDocumentElementNode node, int offset, IDocument doc) {
0461:                int prop_type = determineAssistType(node, doc, offset);
0462:                switch (prop_type) {
0463:                case F_ADD_ATTRIB:
0464:                    return computeAddAttributeProposal(F_INFER_BY_OBJECT, node,
0465:                            offset, doc, null, node.getXMLTagName());
0466:                case F_OPEN_TAG:
0467:                    return computeOpenTagProposal(node, offset, doc);
0468:                case F_ADD_CHILD:
0469:                    return computeAddChildProposal(node, offset, doc, null);
0470:                }
0471:                return null;
0472:            }
0473:
0474:            private int determineAssistType(IDocumentElementNode node,
0475:                    IDocument doc, int offset) {
0476:                int len = node.getLength();
0477:                int off = node.getOffset();
0478:                if (len == -1 || off == -1)
0479:                    return F_NO_ASSIST;
0480:
0481:                offset = offset - off; // look locally
0482:                if (offset > node.getXMLTagName().length() + 1) {
0483:                    try {
0484:                        String eleValue = doc.get(off, len);
0485:                        int ind = eleValue.indexOf('>');
0486:                        if (ind > 0 && eleValue.charAt(ind - 1) == '/')
0487:                            ind -= 1;
0488:                        if (offset <= ind) {
0489:                            if (canInsertAttrib(eleValue, offset))
0490:                                return F_ADD_ATTRIB;
0491:                            return F_NO_ASSIST;
0492:                        }
0493:                        ind = eleValue.lastIndexOf('<');
0494:                        if (ind == 0 && offset == len - 1)
0495:                            return F_OPEN_TAG; // childless node - check if it can be cracked open
0496:                        if (ind + 1 < len && eleValue.charAt(ind + 1) == '/'
0497:                                && offset <= ind)
0498:                            return F_ADD_CHILD;
0499:                    } catch (BadLocationException e) {
0500:                    }
0501:                }
0502:                return F_NO_ASSIST;
0503:            }
0504:
0505:            private boolean canInsertAttrib(String eleValue, int offset) {
0506:                // character before offset must be whitespace
0507:                // character on offset must be whitespace, '/' or '>'
0508:                char c = eleValue.charAt(offset);
0509:                return offset - 1 >= 0
0510:                        && Character.isWhitespace(eleValue.charAt(offset - 1))
0511:                        && (Character.isWhitespace(c) || c == '/' || c == '>');
0512:            }
0513:
0514:            private ICompletionProposal[] computeAddChildProposal(
0515:                    IDocumentElementNode node, int offset, IDocument doc,
0516:                    String filter) {
0517:                ArrayList propList = new ArrayList();
0518:                if (node instanceof  IPluginBase) {
0519:                    return computeRootNodeProposals(node, offset, filter);
0520:                } else if (node instanceof  IPluginExtensionPoint) {
0521:                    return null;
0522:                } else {
0523:                    IPluginObject obj = XMLUtil.getTopLevelParent(node);
0524:                    if (obj instanceof  IPluginExtension) {
0525:                        ISchemaElement sElement = XMLUtil.getSchemaElement(
0526:                                node, ((IPluginExtension) obj).getPoint());
0527:                        if ((sElement != null)
0528:                                && (sElement.getType() instanceof  ISchemaComplexType)) {
0529:                            // We have a schema complex type.  Either the element has attributes
0530:                            // or the element has children.					
0531:                            // Generate the list of element proposals
0532:                            TreeSet elementSet = XMLElementProposalComputer
0533:                                    .computeElementProposal(sElement, node);
0534:                            // Filter the list of element proposals
0535:                            Iterator iterator = elementSet.iterator();
0536:                            while (iterator.hasNext()) {
0537:                                addToList(propList, filter,
0538:                                        (ISchemaObject) iterator.next());
0539:                            }
0540:                        } else {
0541:                            return null;
0542:                        }
0543:                    }
0544:                }
0545:                return convertListToProposal(propList, node, offset);
0546:            }
0547:
0548:            private ICompletionProposal[] computeOpenTagProposal(
0549:                    IDocumentElementNode node, int offset, IDocument doc) {
0550:                IPluginObject obj = XMLUtil.getTopLevelParent(node);
0551:                if (obj instanceof  IPluginExtension) {
0552:                    ISchemaElement sElem = XMLUtil.getSchemaElement(node,
0553:                            ((IPluginExtension) obj).getPoint());
0554:                    if (sElem == null)
0555:                        return null;
0556:                    ISchemaCompositor comp = ((ISchemaComplexType) sElem
0557:                            .getType()).getCompositor();
0558:                    if (comp != null)
0559:                        return new ICompletionProposal[] { new XMLCompletionProposal(
0560:                                node, null, offset, this ) };
0561:                }
0562:                return null;
0563:            }
0564:
0565:            private ICompletionProposal[] computeAddAttributeProposal(int type,
0566:                    IDocumentElementNode node, int offset, IDocument doc,
0567:                    String filter, String tag) {
0568:                String nodeName = tag;
0569:                if (nodeName == null && node != null)
0570:                    nodeName = node.getXMLTagName();
0571:                if (type == F_EXTENSION || node instanceof  IPluginExtension) {
0572:                    ISchemaElement sElem = XMLUtil.getSchemaElement(node,
0573:                            node != null ? ((IPluginExtension) node).getPoint()
0574:                                    : null);
0575:                    ISchemaObject[] sAttrs = sElem != null ? sElem
0576:                            .getAttributes()
0577:                            : new ISchemaObject[] {
0578:                                    new VirtualSchemaObject(
0579:                                            IIdentifiable.P_ID,
0580:                                            PDEUIMessages.XMLContentAssistProcessor_extId,
0581:                                            F_ATTRIBUTE),
0582:                                    new VirtualSchemaObject(
0583:                                            IPluginObject.P_NAME,
0584:                                            PDEUIMessages.XMLContentAssistProcessor_extName,
0585:                                            F_ATTRIBUTE),
0586:                                    new VirtualSchemaObject(
0587:                                            IPluginExtension.P_POINT,
0588:                                            PDEUIMessages.XMLContentAssistProcessor_extPoint,
0589:                                            F_ATTRIBUTE) };
0590:                    return computeAttributeProposals(sAttrs, node, offset,
0591:                            filter, nodeName);
0592:                } else if (type == F_EXTENSION_POINT
0593:                        || node instanceof  IPluginExtensionPoint) {
0594:                    ISchemaObject[] sAttrs = new ISchemaObject[] {
0595:                            new VirtualSchemaObject(
0596:                                    IIdentifiable.P_ID,
0597:                                    PDEUIMessages.XMLContentAssistProcessor_extPointId,
0598:                                    F_ATTRIBUTE),
0599:                            new VirtualSchemaObject(
0600:                                    IPluginObject.P_NAME,
0601:                                    PDEUIMessages.XMLContentAssistProcessor_extPointName,
0602:                                    F_ATTRIBUTE),
0603:                            new VirtualSchemaObject(
0604:                                    IPluginExtensionPoint.P_SCHEMA,
0605:                                    PDEUIMessages.XMLContentAssistProcessor_schemaLocation,
0606:                                    F_ATTRIBUTE) };
0607:                    return computeAttributeProposals(sAttrs, node, offset,
0608:                            filter, nodeName);
0609:                } else {
0610:                    IPluginObject obj = XMLUtil.getTopLevelParent(node);
0611:                    if (obj instanceof  IPluginExtension) {
0612:                        ISchemaElement sElem = XMLUtil.getSchemaElement(node,
0613:                                node != null ? ((IPluginExtension) obj)
0614:                                        .getPoint() : null);
0615:                        ISchemaObject[] sAttrs = sElem != null ? sElem
0616:                                .getAttributes() : null;
0617:                        return computeAttributeProposals(sAttrs, node, offset,
0618:                                filter, nodeName);
0619:                    }
0620:                }
0621:                return null;
0622:            }
0623:
0624:            private void addToList(ArrayList list, String filter,
0625:                    ISchemaObject object) {
0626:                if (object == null)
0627:                    return;
0628:                if (filter == null || filter.length() == 0)
0629:                    list.add(object);
0630:                else {
0631:                    String name = object.getName();
0632:                    if (filter.regionMatches(true, 0, name, 0, filter.length()))
0633:                        list.add(object);
0634:                }
0635:            }
0636:
0637:            private ICompletionProposal[] computeBrokenModelProposal(
0638:                    IDocumentElementNode parent, int offset, IDocument doc) {
0639:                if (parent == null)
0640:                    return null;
0641:
0642:                int[] offArr = new int[] { offset, offset, offset };
0643:                String[] guess = guessContentRequest(offArr, doc, true);
0644:                if (guess == null)
0645:                    return null;
0646:
0647:                int elRepOffset = offArr[0];
0648:                int atRepOffset = offArr[1];
0649:                int atValRepOffest = offArr[2];
0650:                String element = guess[0];
0651:                String attr = guess[1];
0652:                String attVal = guess[2];
0653:
0654:                IPluginObject obj = XMLUtil.getTopLevelParent(parent);
0655:                if (obj instanceof  IPluginExtension) {
0656:                    String point = ((IPluginExtension) obj).getPoint();
0657:                    if (attr == null)
0658:                        // search for element proposals
0659:                        return computeAddChildProposal(parent, elRepOffset,
0660:                                doc, element);
0661:
0662:                    ISchemaElement sEle = XMLUtil.getSchemaElement(parent,
0663:                            point);
0664:                    if (sEle == null)
0665:                        return null;
0666:                    sEle = sEle.getSchema().findElement(element);
0667:                    if (sEle == null)
0668:                        return null;
0669:
0670:                    if (attr.indexOf('=') != -1)
0671:                        // search for attribute content proposals
0672:                        return computeBrokenModelAttributeContentProposal(
0673:                                parent, atValRepOffest, element, attr, attVal);
0674:
0675:                    // search for attribute proposals
0676:                    return computeAttributeProposals(sEle.getAttributes(),
0677:                            null, atRepOffset, attr, element);
0678:                } else if (parent instanceof  IPluginBase) {
0679:                    if (attr == null)
0680:                        return computeAddChildProposal(parent, elRepOffset,
0681:                                doc, element);
0682:                    if (element.equalsIgnoreCase(F_STR_EXT))
0683:                        return computeAddAttributeProposal(F_EXTENSION, null,
0684:                                atRepOffset, doc, attr, F_STR_EXT);
0685:                    if (element.equalsIgnoreCase(F_STR_EXT_PT))
0686:                        return computeAddAttributeProposal(F_EXTENSION_POINT,
0687:                                null, atRepOffset, doc, attr, F_STR_EXT_PT);
0688:                }
0689:                return null;
0690:            }
0691:
0692:            private ICompletionProposal[] computeBrokenModelAttributeContentProposal(
0693:                    IDocumentElementNode parent, int offset, String element,
0694:                    String attr, String filter) {
0695:                // TODO use computeCompletionProposal(IDocumentAttributeNode attr, int offset) if possible
0696:                // or refactor above to be used here
0697:                // CURRENTLY: attribute completion only works in non-broken models
0698:                return null;
0699:            }
0700:
0701:            private String[] guessContentRequest(int[] offset, IDocument doc,
0702:                    boolean brokenModel) {
0703:                StringBuffer nodeBuffer = new StringBuffer();
0704:                StringBuffer attrBuffer = new StringBuffer();
0705:                StringBuffer attrValBuffer = new StringBuffer();
0706:                String node = null;
0707:                String attr = null;
0708:                String attVal = null;
0709:                int quoteCount = 0;
0710:                try {
0711:                    while (--offset[0] >= 0) {
0712:                        char c = doc.getChar(offset[0]);
0713:                        if (c == '"') {
0714:                            quoteCount += 1;
0715:                            nodeBuffer.setLength(0);
0716:                            attrBuffer.setLength(0);
0717:                            if (attVal != null) // ran into 2nd quotation mark, we are out of range
0718:                                continue;
0719:                            offset[2] = offset[0];
0720:                            attVal = attrValBuffer.toString();
0721:                        } else if (Character.isWhitespace(c)) {
0722:                            nodeBuffer.setLength(0);
0723:                            if (attr == null) {
0724:                                offset[1] = offset[0];
0725:                                int attBuffLen = attrBuffer.length();
0726:                                if (attBuffLen > 0
0727:                                        && attrBuffer.charAt(attBuffLen - 1) == '=')
0728:                                    attrBuffer.setLength(attBuffLen - 1);
0729:                                attr = attrBuffer.toString();
0730:                            }
0731:                        } else if (c == '<') {
0732:                            node = nodeBuffer.toString();
0733:                            break;
0734:                        } else if (c == '>') {
0735:                            // only enable content assist if user is inside an open tag
0736:                            return null;
0737:                        } else {
0738:                            attrValBuffer.insert(0, c);
0739:                            attrBuffer.insert(0, c);
0740:                            nodeBuffer.insert(0, c);
0741:                        }
0742:                    }
0743:                } catch (BadLocationException e) {
0744:                }
0745:                if (node == null)
0746:                    return null;
0747:
0748:                if (quoteCount % 2 == 0)
0749:                    attVal = null;
0750:                else if (brokenModel)
0751:                    return null; // open quotes - don't provide assist
0752:
0753:                return new String[] { node, attr, attVal };
0754:            }
0755:
0756:            protected IBaseModel getModel() {
0757:                return fSourcePage.getInputContext().getModel();
0758:            }
0759:
0760:            protected ITextSelection getCurrentSelection() {
0761:                ISelection sel = fSourcePage.getSelectionProvider()
0762:                        .getSelection();
0763:                if (sel instanceof  ITextSelection)
0764:                    return (ITextSelection) sel;
0765:                return null;
0766:            }
0767:
0768:            protected void flushDocument() {
0769:                fSourcePage.getInputContext().flushEditorInput();
0770:            }
0771:
0772:            private ICompletionProposal[] computeAttributeProposals(
0773:                    ISchemaObject[] sAttrs, IDocumentElementNode node,
0774:                    int offset, String filter, String parentName) {
0775:                if (sAttrs == null || sAttrs.length == 0)
0776:                    return null;
0777:                IDocumentAttributeNode[] attrs = node != null ? node
0778:                        .getNodeAttributes() : new IDocumentAttributeNode[0];
0779:
0780:                ArrayList list = new ArrayList();
0781:                for (int i = 0; i < sAttrs.length; i++) {
0782:                    int k; // if we break early we wont add
0783:                    for (k = 0; k < attrs.length; k++)
0784:                        if (attrs[k].getAttributeName().equals(
0785:                                sAttrs[i].getName()))
0786:                            break;
0787:                    if (k == attrs.length)
0788:                        addToList(list, filter, sAttrs[i]);
0789:                }
0790:                if (filter != null && filter.length() == 0)
0791:                    list.add(0, new VirtualSchemaObject(parentName, null,
0792:                            F_CLOSE_TAG));
0793:                return convertListToProposal(list, node, offset);
0794:            }
0795:
0796:            private ICompletionProposal[] convertListToProposal(ArrayList list,
0797:                    IDocumentRange range, int offset) {
0798:                ICompletionProposal[] proposals = new ICompletionProposal[list
0799:                        .size()];
0800:                if (proposals.length == 0)
0801:                    return null;
0802:                for (int i = 0; i < proposals.length; i++)
0803:                    proposals[i] = new XMLCompletionProposal(range,
0804:                            (ISchemaObject) list.get(i), offset, this );
0805:                return proposals;
0806:            }
0807:
0808:            public void assistSessionEnded(ContentAssistEvent event) {
0809:                fRange = null;
0810:
0811:                // Reset cached internal and external extension point proposals
0812:                fAllExtPoints = null;
0813:                // Reset cached internal point proposals
0814:                // Note: Not resetting cached external point proposals
0815:                // Assumption is that the users workspace can change; but, not the
0816:                // platform including all the external plugins
0817:                fInternalExtPoints = null;
0818:
0819:                fDocLen = -1;
0820:            }
0821:
0822:            public void assistSessionStarted(ContentAssistEvent event) {
0823:                fAssistSessionStarted = true;
0824:            }
0825:
0826:            public void selectionChanged(ICompletionProposal proposal,
0827:                    boolean smartToggle) {
0828:            }
0829:
0830:            /**
0831:             * @param vSchemaType
0832:             * @return
0833:             */
0834:            private ArrayList getAllExtensionPoints(int vSchemaType) {
0835:                // Return the previous extension points if defined
0836:                if (fAllExtPoints != null) {
0837:                    return fAllExtPoints;
0838:                }
0839:                // Get the plugin model base 
0840:                IPluginModelBase model = getPluginModelBase();
0841:                // Note: All plug-in extension points are cached except the 
0842:                // extension points defined by the plugin.xml we are currently 
0843:                // editing. This means if a plug-in in the workspace defines a new
0844:                // extension point and the plugin.xml editor is still open, the 
0845:                // new extension point will not show up as a proposal because it is
0846:                // using a cached list of extension points.
0847:                // External extensions points are all extension points not defined by
0848:                // the plugin currently being edited - opposed to non-workpspace
0849:                // plugins.  Internal extension points are the extension points defined
0850:                // by the plugin currently being edited.  May want to modify this
0851:                // behaviour in the future.
0852:                // Add all external extension point proposals to the list
0853:                fAllExtPoints = (ArrayList) getExternalExtensionPoints(model,
0854:                        vSchemaType).clone();
0855:                // Add all internal extension point proposals to the list
0856:                fAllExtPoints.addAll(getInternalExtensionPoints(model,
0857:                        vSchemaType));
0858:
0859:                return fAllExtPoints;
0860:            }
0861:
0862:            /**
0863:             * @param model
0864:             * @return
0865:             */
0866:            private ArrayList getExternalExtensionPoints(
0867:                    IPluginModelBase model, int vSchemaType) {
0868:                // Return the previous external extension points if defined
0869:                if (fExternalExtPoints != null) {
0870:                    updateExternalExtPointTypes(vSchemaType);
0871:                    return fExternalExtPoints;
0872:                }
0873:                // Query for all external extension points
0874:                fExternalExtPoints = new ArrayList();
0875:                // Get all plug-ins in the workspace
0876:                IPluginModelBase[] plugins = PluginRegistry.getActiveModels();
0877:                // Process each plugin
0878:                for (int i = 0; i < plugins.length; i++) {
0879:                    // Make sure this plugin is not the one we are currently 
0880:                    // editing which defines internal extension points.
0881:                    // We don't want to cache internal extension points because the
0882:                    // workspace can change.
0883:                    if (plugins[i].getPluginBase().getId().equals(
0884:                            model.getPluginBase().getId())) {
0885:                        // Skip this plugin
0886:                        continue;
0887:                    }
0888:                    // Get all extension points defined by this plugin
0889:                    IPluginExtensionPoint[] points = plugins[i].getPluginBase()
0890:                            .getExtensionPoints();
0891:                    // Process each extension point
0892:                    for (int j = 0; j < points.length; j++) {
0893:                        VirtualSchemaObject vObject = new VirtualSchemaObject(
0894:                                IdUtil.getFullId(points[j], model), points[j],
0895:                                vSchemaType);
0896:                        // Add the proposal to the list
0897:                        fExternalExtPoints.add(vObject);
0898:                    }
0899:                }
0900:                return fExternalExtPoints;
0901:            }
0902:
0903:            /**
0904:             * Handles edge case.
0905:             * External extension points are cached.
0906:             * As a result, these types persist over each other depending on what 
0907:             * context content assist is invoked first:
0908:             * F_EXTENSION_ATTRIBUTE_POINT_VALUE
0909:             * F_EXTENSION_POINT_AND_VALUE
0910:             * @param newVType
0911:             */
0912:            private void updateExternalExtPointTypes(int newVType) {
0913:                // Ensure we have proposals
0914:                if (fExternalExtPoints.size() == 0) {
0915:                    return;
0916:                }
0917:                // Get the first proposal
0918:                VirtualSchemaObject vObject = (VirtualSchemaObject) fExternalExtPoints
0919:                        .get(0);
0920:                // If the first proposals type is the same as the new type, then we
0921:                // do not have to do the update.  That is because all the proposals
0922:                // have the same type. 
0923:                if (vObject.getVType() == newVType) {
0924:                    return;
0925:                }
0926:                // Update all the proposals with the new type
0927:                Iterator iterator = fExternalExtPoints.iterator();
0928:                while (iterator.hasNext()) {
0929:                    ((VirtualSchemaObject) iterator.next()).setVType(newVType);
0930:                }
0931:            }
0932:
0933:            /**
0934:             * @param model
0935:             * @return
0936:             */
0937:            private ArrayList getInternalExtensionPoints(
0938:                    IPluginModelBase model, int vSchemaType) {
0939:                // Return the previous internal extension points if defined
0940:                if (fInternalExtPoints != null) {
0941:                    // Realistically, this line should never be hit
0942:                    return fInternalExtPoints;
0943:                }
0944:                fInternalExtPoints = new ArrayList();
0945:                // Get all extension points defined by this plugin
0946:                IPluginExtensionPoint[] points = model.getPluginBase()
0947:                        .getExtensionPoints();
0948:                // Process each extension point
0949:                for (int j = 0; j < points.length; j++) {
0950:                    VirtualSchemaObject vObject = new VirtualSchemaObject(
0951:                            IdUtil.getFullId(points[j], model), points[j],
0952:                            vSchemaType);
0953:                    // Add the proposal to the list
0954:                    fInternalExtPoints.add(vObject);
0955:                }
0956:                return fInternalExtPoints;
0957:            }
0958:
0959:            /**
0960:             * Returns a BundlePluginModel which has a getId() method that works.
0961:             * getModel() method returns a PluginModel whose getId() method does not
0962:             * work.
0963:             * @return 
0964:             */
0965:            private IPluginModelBase getPluginModelBase() {
0966:                FormEditor formEditor = fSourcePage.getEditor();
0967:                if ((formEditor instanceof  PDEFormEditor) == false) {
0968:                    return null;
0969:                }
0970:                IBaseModel bModel = ((PDEFormEditor) formEditor)
0971:                        .getAggregateModel();
0972:                if ((bModel instanceof  IPluginModelBase) == false) {
0973:                    return null;
0974:                }
0975:                return (IPluginModelBase) bModel;
0976:            }
0977:
0978:            public Image getImage(int type) {
0979:                if (fImages[type] == null) {
0980:                    switch (type) {
0981:                    case F_EXTENSION_POINT:
0982:                    case F_EXTENSION_ATTRIBUTE_POINT_VALUE:
0983:                        return fImages[type] = PDEPluginImages.DESC_EXT_POINT_OBJ
0984:                                .createImage();
0985:                    case F_EXTENSION_POINT_AND_VALUE:
0986:                    case F_EXTENSION:
0987:                        return fImages[type] = PDEPluginImages.DESC_EXTENSION_OBJ
0988:                                .createImage();
0989:                    case F_ELEMENT:
0990:                    case F_CLOSE_TAG:
0991:                        return fImages[type] = PDEPluginImages.DESC_XML_ELEMENT_OBJ
0992:                                .createImage();
0993:                    case F_ATTRIBUTE:
0994:                    case F_ATTRIBUTE_VALUE:
0995:                        return fImages[type] = PDEPluginImages.DESC_ATT_URI_OBJ
0996:                                .createImage();
0997:                    }
0998:                }
0999:                return fImages[type];
1000:            }
1001:
1002:            public void dispose() {
1003:                for (int i = 0; i < fImages.length; i++)
1004:                    if (fImages[i] != null && !fImages[i].isDisposed())
1005:                        fImages[i].dispose();
1006:            }
1007:
1008:            /**
1009:             * @return
1010:             */
1011:            public PDESourcePage getSourcePage() {
1012:                return fSourcePage;
1013:            }
1014:
1015:        }
www_._j__ava2s_.__c__om | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.