| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.netbeans.modules.j2ee.persistence.editor.completion; |
| |
| import java.io.IOException; |
| import java.util.*; |
| import javax.lang.model.element.Element; |
| import javax.lang.model.element.ElementKind; |
| import javax.lang.model.element.TypeElement; |
| import javax.lang.model.element.VariableElement; |
| import javax.swing.text.Document; |
| import org.netbeans.api.db.explorer.ConnectionManager; |
| import org.netbeans.api.db.explorer.DatabaseConnection; |
| import org.netbeans.api.java.source.CompilationController; |
| import org.netbeans.api.java.source.ElementHandle; |
| import org.netbeans.api.java.source.JavaSource; |
| import org.netbeans.api.java.source.JavaSource.Phase; |
| import org.netbeans.api.java.source.Task; |
| import org.netbeans.api.project.FileOwnerQuery; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.modules.editor.NbEditorUtilities; |
| import org.netbeans.modules.j2ee.metadata.model.api.MetadataModelAction; |
| import org.netbeans.modules.j2ee.persistence.api.EntityClassScope; |
| import org.netbeans.modules.j2ee.persistence.api.metadata.orm.Entity; |
| import org.netbeans.modules.j2ee.persistence.api.metadata.orm.EntityMappingsMetadata; |
| import org.netbeans.modules.j2ee.persistence.dd.common.Persistence; |
| import org.netbeans.modules.j2ee.persistence.editor.CompletionContext; |
| import org.netbeans.modules.j2ee.persistence.editor.JPAEditorUtil; |
| import org.netbeans.modules.j2ee.persistence.provider.Provider; |
| import org.netbeans.modules.j2ee.persistence.provider.ProviderUtil; |
| import org.netbeans.modules.j2ee.persistence.spi.EntityClassScopeProvider; |
| import org.netbeans.modules.j2ee.persistence.spi.datasource.JPADataSource; |
| import org.netbeans.modules.j2ee.persistence.spi.datasource.JPADataSourceProvider; |
| import org.netbeans.modules.j2ee.persistence.wizard.Util; |
| import org.openide.filesystems.FileObject; |
| import org.openide.util.Exceptions; |
| import org.w3c.dom.Node; |
| |
| /** |
| * Various completor for code completing XML tags and attributes in Hibername |
| * configuration and mapping file |
| * |
| * @author Dongmei Cao |
| */ |
| public abstract class PUCompletor { |
| |
| |
| static class JtaDatasourceCompletor extends PUCompletor { |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| Project project = FileOwnerQuery.getOwner( |
| NbEditorUtilities.getFileObject(context.getDocument())); |
| JPADataSourceProvider dsProvider = project.getLookup().lookup(JPADataSourceProvider.class); |
| if(dsProvider != null){ |
| for (JPADataSource val : dsProvider.getDataSources()) { |
| if(val.getDisplayName().toLowerCase().startsWith(typedChars.trim().toLowerCase())){ |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| val.getDisplayName()); |
| results.add(item); |
| } |
| } |
| } |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| static class ProviderCompletor extends PUCompletor { |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| HashSet<String> providers = new HashSet<String>(); |
| Project project = FileOwnerQuery.getOwner( |
| NbEditorUtilities.getFileObject(context.getDocument())); |
| for(Provider provider: Util.getProviders(project)){ |
| String cl = provider.getProviderClass(); |
| if(cl.toLowerCase().startsWith(typedChars.trim().toLowerCase())){ |
| providers.add(cl); |
| } |
| } |
| |
| for (String cl: providers) { |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| cl); |
| results.add(item); |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| |
| static class ExUnlistedClassesCompletor extends PUCompletor { |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| for (String val : new String[]{"true", "false"}) {//NOI18N |
| if(val.toLowerCase().startsWith(typedChars.trim().toLowerCase())){ |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| val); |
| results.add(item); |
| } |
| } |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| |
| private int anchorOffset = -1; |
| |
| public abstract List<JPACompletionItem> doCompletion(CompletionContext context); |
| |
| protected void setAnchorOffset(int anchorOffset) { |
| this.anchorOffset = anchorOffset; |
| } |
| |
| public int getAnchorOffset() { |
| return anchorOffset; |
| } |
| |
| /** |
| * A simple completor for general attribute value items |
| * |
| * Takes an array of strings, the even elements being the display text of |
| * the items and the odd ones being the corresponding documentation of the |
| * items |
| * |
| */ |
| public static class AttributeValueCompletor extends PUCompletor { |
| |
| private String[] itemTexts; |
| |
| public AttributeValueCompletor(String[] itemTextAndDocs) { |
| this.itemTexts = itemTextAndDocs; |
| } |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| |
| for (int i = 0; i < itemTexts.length; i += 1) { |
| if (itemTexts[i].startsWith(typedChars.trim())) { |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| itemTexts[i]); |
| results.add(item); |
| } |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| /** |
| * A completor for completing class tag |
| */ |
| public static class EntityClassCompletor extends PUCompletor { |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(final CompletionContext context) { |
| final List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| try { |
| Document doc = context.getDocument(); |
| final String typedChars = context.getTypedPrefix(); |
| |
| JavaSource js = JPAEditorUtil.getJavaSource(doc); |
| if (js == null) { |
| return Collections.emptyList(); |
| } |
| FileObject fo = NbEditorUtilities.getFileObject(context.getDocument()); |
| doJavaCompletion(fo, js, results, typedChars, context.getCurrentTokenOffset()); |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| |
| return results; |
| } |
| |
| private void doJavaCompletion(final FileObject fo, final JavaSource js, final List<JPACompletionItem> results, |
| final String typedPrefix, final int substitutionOffset) throws IOException { |
| js.runUserActionTask(new Task<CompilationController>() { |
| |
| @Override |
| public void run(CompilationController cc) throws Exception { |
| cc.toPhase(Phase.ELEMENTS_RESOLVED); |
| Project project = FileOwnerQuery.getOwner(fo); |
| EntityClassScopeProvider provider = (EntityClassScopeProvider) project.getLookup().lookup(EntityClassScopeProvider.class); |
| EntityClassScope ecs = null; |
| Entity[] entities = null; |
| if (provider != null) { |
| ecs = provider.findEntityClassScope(fo); |
| } |
| if (ecs != null) { |
| entities = ecs.getEntityMappingsModel(false).runReadAction(new MetadataModelAction<EntityMappingsMetadata, Entity[]>() { |
| |
| @Override |
| public Entity[] run(EntityMappingsMetadata metadata) throws Exception { |
| return metadata.getRoot().getEntity(); |
| } |
| }); |
| } |
| // add classes |
| if(entities != null) { |
| for (Entity entity : entities) { |
| if (typedPrefix.length() == 0 || entity.getClass2().toLowerCase().startsWith(typedPrefix.toLowerCase()) || entity.getName().toLowerCase().startsWith(typedPrefix.toLowerCase())) { |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(substitutionOffset, entity.getClass2()); |
| results.add(item); |
| } |
| } |
| } |
| } |
| }, true); |
| |
| setAnchorOffset(substitutionOffset); |
| } |
| } |
| |
| /** |
| * A completor for completing Java properties/fields attributes |
| */ |
| public static class PropertyCompletor extends PUCompletor { |
| |
| public PropertyCompletor() { |
| } |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(final CompletionContext context) { |
| |
| final List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| final int caretOffset = context.getCaretOffset(); |
| final String typedChars = context.getTypedPrefix(); |
| |
| final String className = JPAEditorUtil.getClassName(context.getTag()); |
| if (className == null) { |
| return Collections.emptyList(); |
| } |
| |
| try { |
| // Compile the class and find the fiels |
| JavaSource classJavaSrc = JPAEditorUtil.getJavaSource(context.getDocument()); |
| classJavaSrc.runUserActionTask(new Task<CompilationController>() { |
| |
| @Override |
| public void run(CompilationController cc) throws Exception { |
| cc.toPhase(Phase.ELEMENTS_RESOLVED); |
| TypeElement typeElem = cc.getElements().getTypeElement(className); |
| |
| if (typeElem == null) { |
| return; |
| } |
| |
| List<? extends Element> clsChildren = typeElem.getEnclosedElements(); |
| for (Element clsChild : clsChildren) { |
| if (clsChild.getKind() == ElementKind.FIELD) { |
| VariableElement elem = (VariableElement) clsChild; |
| JPACompletionItem item = JPACompletionItem.createClassPropertyItem(caretOffset - typedChars.length(), elem, ElementHandle.create(elem), cc.getElements().isDeprecated(clsChild)); |
| results.add(item); |
| } |
| } |
| } |
| }, true); |
| |
| |
| } catch (IOException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| |
| return results; |
| } |
| } |
| |
| /** |
| * A completor for completing the persistence property names in |
| * persistence.xml file |
| * |
| */ |
| public static class PersistencePropertyNameCompletor extends PUCompletor { |
| |
| private Map<Provider, Map<String, String[]>> allKeyAndValues; |
| |
| PersistencePropertyNameCompletor(Map<Provider, Map<String, String[]>> allKeyAndValues) { |
| this.allKeyAndValues = allKeyAndValues; |
| } |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| String providerClass = getProviderClass(context.getTag()); |
| Project enclosingProject = FileOwnerQuery.getOwner( |
| NbEditorUtilities.getFileObject(context.getDocument())); |
| Provider provider = ProviderUtil.getProvider(providerClass, enclosingProject); |
| ArrayList<String> keys = new ArrayList<String>(); |
| String ver = provider == null ? context.getDocumentContext().getVersion() : ProviderUtil.getVersion(provider); |
| if (provider == null || (ver!=null && !Persistence.VERSION_1_0.equals(ver))) { |
| keys.addAll(allKeyAndValues.get(null).keySet()); |
| } |
| if (provider != null && allKeyAndValues.get(provider) != null) { |
| keys.addAll(allKeyAndValues.get(provider).keySet()); |
| } |
| String itemTexts[] = keys.toArray(new String[]{}); |
| for (int i = 0; i < itemTexts.length; i++) { |
| if (itemTexts[i].startsWith(typedChars.trim()) |
| || itemTexts[i].startsWith("javax.persistence." + typedChars.trim())) { // NOI18N |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| itemTexts[i]); |
| results.add(item); |
| } |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| /** |
| * A completor for completing the persistence property value in |
| * persistence.xml file |
| * |
| */ |
| public static class PersistencePropertyValueCompletor extends PUCompletor { |
| |
| private Map<Provider, Map<String, String[]>> allKeyAndValues; |
| |
| PersistencePropertyValueCompletor(Map<Provider, Map<String, String[]>> allKeyAndValues) { |
| this.allKeyAndValues = allKeyAndValues; |
| } |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| String propertyName = getPropertyName(context.getTag()); |
| if (propertyName == null || propertyName.equals("")) { |
| return results; |
| } |
| String providerClass = getProviderClass(context.getTag()); |
| Project enclosingProject = FileOwnerQuery.getOwner( |
| NbEditorUtilities.getFileObject(context.getDocument())); |
| Provider provider = ProviderUtil.getProvider(providerClass, enclosingProject); |
| String[] values = null; |
| String ver = provider == null ? context.getDocumentContext().getVersion() : ProviderUtil.getVersion(provider); |
| if (provider == null || (ver!=null && !Persistence.VERSION_1_0.equals(ver))) { |
| values = allKeyAndValues.get(null).get(propertyName); |
| } |
| if (provider != null && allKeyAndValues.get(provider) != null) { |
| String [] tmp2 = allKeyAndValues.get(provider).get(propertyName); |
| if(tmp2 != null) { |
| values = tmp2; |
| } |
| if (values == null && propertyName.equals(provider.getJdbcUrl())) { |
| |
| //always allow this property completion, even for container managed(it's in jta-data-source tag, not in properties) |
| DatabaseConnection[] cns = ConnectionManager.getDefault().getConnections(); |
| for (DatabaseConnection cn : cns) { |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| cn.getDatabaseURL()); |
| results.add(item); |
| } |
| results.add(new JPACompletionItem.AddConnectionElementItem()); |
| } |
| } |
| if (values != null) { |
| for (int i = 0; i < values.length; i++) { |
| JPACompletionItem item = JPACompletionItem.createAttribValueItem(caretOffset - typedChars.length(), |
| values[i]); |
| results.add(item); |
| } |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| } |
| |
| /** |
| * A completor for completing orm mapping files |
| */ |
| public static class PersistenceMappingFileCompletor extends PUCompletor { |
| |
| public PersistenceMappingFileCompletor() { |
| } |
| |
| @Override |
| public List<JPACompletionItem> doCompletion(CompletionContext context) { |
| List<JPACompletionItem> results = new ArrayList<JPACompletionItem>(); |
| int caretOffset = context.getCaretOffset(); |
| String typedChars = context.getTypedPrefix(); |
| |
| String[] mappingFiles = getMappingFilesFromProject(context); |
| |
| for (int i = 0; i < mappingFiles.length; i++) { |
| if (mappingFiles[i].startsWith(typedChars.trim())) { |
| JPACompletionItem item = |
| JPACompletionItem.createMappingFileItem(caretOffset - typedChars.length(), |
| mappingFiles[i]); |
| results.add(item); |
| } |
| } |
| |
| setAnchorOffset(context.getCurrentTokenOffset() + 1); |
| return results; |
| } |
| |
| // Gets the list of mapping files. |
| private String[] getMappingFilesFromProject(CompletionContext context) { |
| Project enclosingProject = FileOwnerQuery.getOwner( |
| NbEditorUtilities.getFileObject(context.getDocument())); |
| //use persistence environment when will be supported |
| if (null != null) { |
| return null; |
| } else { |
| return new String[0]; |
| } |
| |
| } |
| } |
| |
| private static String getProviderClass(Node tag) { |
| String name = null; |
| while (tag != null && !"persistence-unit".equals(tag.getNodeName())) { |
| tag = tag.getParentNode();//NOI18N |
| } |
| if (tag != null) { |
| for (Node ch = tag.getFirstChild(); ch != null; ch = ch.getNextSibling()) { |
| if ("provider".equals(ch.getNodeName())) {//NOI18N |
| name = ch.getFirstChild().getNodeValue(); |
| } |
| } |
| } |
| return name; |
| } |
| |
| private static String getPropertyName(Node tag) { |
| String name = null; |
| while (tag != null && !"property".equals(tag.getNodeName())) { |
| tag = tag.getParentNode();//NOI18N |
| } |
| if (tag != null) { |
| Node nmN = tag.getAttributes().getNamedItem("name");//NOI18N |
| if (nmN != null) { |
| name = nmN.getNodeValue(); |
| } |
| } |
| return name; |
| } |
| } |