/* * 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.apache.directory.studio.ldifeditor.editor.text; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.directory.api.util.Strings; import org.apache.directory.studio.ldapbrowser.core.BrowserCoreConstants; import org.apache.directory.studio.ldapbrowser.core.model.schema.Schema; import org.apache.directory.studio.ldapbrowser.core.model.schema.SchemaUtils; import org.apache.directory.studio.ldifeditor.LdifEditorActivator; import org.apache.directory.studio.ldifeditor.LdifEditorConstants; import org.apache.directory.studio.ldifeditor.editor.ILdifEditor; import org.apache.directory.studio.ldifparser.model.LdifFile; import org.apache.directory.studio.ldifparser.model.LdifInvalidPart; import org.apache.directory.studio.ldifparser.model.LdifPart; import org.apache.directory.studio.ldifparser.model.container.LdifChangeAddRecord; import org.apache.directory.studio.ldifparser.model.container.LdifChangeModDnRecord; import org.apache.directory.studio.ldifparser.model.container.LdifChangeModifyRecord; import org.apache.directory.studio.ldifparser.model.container.LdifContainer; import org.apache.directory.studio.ldifparser.model.container.LdifContentRecord; import org.apache.directory.studio.ldifparser.model.container.LdifInvalidContainer; import org.apache.directory.studio.ldifparser.model.container.LdifModSpec; import org.apache.directory.studio.ldifparser.model.container.LdifRecord; import org.apache.directory.studio.ldifparser.model.container.LdifSepContainer; import org.apache.directory.studio.ldifparser.model.lines.LdifAttrValLine; import org.apache.directory.studio.ldifparser.model.lines.LdifChangeTypeLine; import org.apache.directory.studio.ldifparser.model.lines.LdifSepLine; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.contentassist.CompletionProposal; import org.eclipse.jface.text.contentassist.ContentAssistant; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateCompletionProcessor; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.swt.graphics.Image; public class LdifCompletionProcessor extends TemplateCompletionProcessor { // private final static String Dn = "dn: "; private final static String CT_ADD = "changetype: add" + BrowserCoreConstants.LINE_SEPARATOR; //$NON-NLS-1$ private final static String CT_MODIFY = "changetype: modify" + BrowserCoreConstants.LINE_SEPARATOR; //$NON-NLS-1$ private final static String CT_DELETE = "changetype: delete" + BrowserCoreConstants.LINE_SEPARATOR; //$NON-NLS-1$ private final static String CT_MODDN = "changetype: moddn" + BrowserCoreConstants.LINE_SEPARATOR; //$NON-NLS-1$ private final static String MD_NEWRDN = "newrdn: "; //$NON-NLS-1$ private final static String MD_DELETEOLDRDN_TRUE = "deleteoldrdn: 1"; //$NON-NLS-1$ // private final static String MD_DELETEOLDRDN_FALSE = "deleteoldrdn: // 0"; private final static String MD_NEWSUPERIOR = "newsuperior: "; //$NON-NLS-1$ private final ILdifEditor editor; private final ContentAssistant contentAssistant; public LdifCompletionProcessor( ILdifEditor editor, ContentAssistant contentAssistant ) { this.editor = editor; this.contentAssistant = contentAssistant; } public ICompletionProposal[] computeCompletionProposals( ITextViewer viewer, int offset ) { IPreferenceStore store = LdifEditorActivator.getDefault().getPreferenceStore(); contentAssistant.enableAutoInsert( store .getBoolean( LdifEditorConstants.PREFERENCE_LDIFEDITOR_CONTENTASSIST_INSERTSINGLEPROPOSALAUTO ) ); contentAssistant.enableAutoActivation( store .getBoolean( LdifEditorConstants.PREFERENCE_LDIFEDITOR_CONTENTASSIST_ENABLEAUTOACTIVATION ) ); contentAssistant.setAutoActivationDelay( store .getInt( LdifEditorConstants.PREFERENCE_LDIFEDITOR_CONTENTASSIST_AUTOACTIVATIONDELAY ) ); List<ICompletionProposal> proposalList = new ArrayList<ICompletionProposal>(); LdifFile model = editor.getLdifModel(); LdifContainer container = LdifFile.getContainer( model, offset ); LdifContainer innerContainer = container != null ? LdifFile.getInnerContainer( container, offset ) : null; LdifPart part = container != null ? LdifFile.getContainerContent( container, offset ) : null; int documentLine = -1; int documentLineOffset = -1; String prefix = ""; //$NON-NLS-1$ try { documentLine = viewer.getDocument().getLineOfOffset( offset ); documentLineOffset = viewer.getDocument().getLineOffset( documentLine ); prefix = viewer.getDocument().get( documentLineOffset, offset - documentLineOffset ); } catch ( BadLocationException e ) { } // TemplateContextType contextType = getContextType(viewer, new // Region(offset, 0)); // Add context dependend template proposals ICompletionProposal[] templateProposals = super.computeCompletionProposals( viewer, offset ); if ( templateProposals != null ) { proposalList.addAll( Arrays.asList( templateProposals ) ); } // changetype: xxx if ( container instanceof LdifRecord ) { LdifRecord record = ( LdifRecord ) container; LdifPart[] parts = record.getParts(); if ( parts.length > 1 && ( !( parts[1] instanceof LdifChangeTypeLine ) || !parts[1].isValid() ) ) { if ( CT_ADD.startsWith( prefix ) ) proposalList.add( new CompletionProposal( CT_ADD, offset - prefix.length(), prefix.length(), CT_ADD .length(), LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_ADD ), CT_ADD.substring( 0, CT_ADD.length() - BrowserCoreConstants.LINE_SEPARATOR.length() ), null, null ) ); if ( CT_MODIFY.startsWith( prefix ) ) proposalList.add( new CompletionProposal( CT_MODIFY, offset - prefix.length(), prefix.length(), CT_MODIFY.length(), LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MODIFY ), CT_MODIFY.substring( 0, CT_MODIFY.length() - BrowserCoreConstants.LINE_SEPARATOR.length() ), null, null ) ); if ( CT_DELETE.startsWith( prefix ) ) proposalList.add( new CompletionProposal( CT_DELETE, offset - prefix.length(), prefix.length(), CT_DELETE.length(), LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_DELETE ), CT_DELETE.substring( 0, CT_DELETE.length() - BrowserCoreConstants.LINE_SEPARATOR.length() ), null, null ) ); if ( CT_MODDN.startsWith( prefix ) ) proposalList.add( new CompletionProposal( CT_MODDN, offset - prefix.length(), prefix.length(), CT_MODDN.length(), LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_RENAME ), CT_MODDN.substring( 0, CT_MODDN.length() - BrowserCoreConstants.LINE_SEPARATOR.length() ), null, null ) ); } } // changetype: modify if ( container instanceof LdifChangeModDnRecord ) { LdifChangeModDnRecord record = ( LdifChangeModDnRecord ) container; if ( ( record.getNewrdnLine() == null || !record.getNewrdnLine().isValid() ) && MD_NEWRDN.startsWith( prefix ) ) { proposalList.add( new CompletionProposal( MD_NEWRDN, offset - prefix.length(), prefix.length(), MD_NEWRDN.length(), null, null, null, null ) ); } if ( ( record.getDeloldrdnLine() == null || !record.getDeloldrdnLine().isValid() ) && MD_DELETEOLDRDN_TRUE.startsWith( prefix ) ) { proposalList.add( new CompletionProposal( MD_DELETEOLDRDN_TRUE, offset - prefix.length(), prefix .length(), MD_DELETEOLDRDN_TRUE.length(), null, null, null, null ) ); } if ( ( record.getNewsuperiorLine() == null || !record.getNewsuperiorLine().isValid() ) && MD_NEWSUPERIOR.startsWith( prefix ) ) { proposalList.add( new CompletionProposal( MD_NEWSUPERIOR, offset - prefix.length(), prefix.length(), MD_NEWSUPERIOR.length(), null, null, null, null ) ); } } // modspecs if ( innerContainer instanceof LdifModSpec ) { LdifModSpec modSpec = ( LdifModSpec ) innerContainer; String att = modSpec.getModSpecType().getRawAttributeDescription(); if ( att != null && att.startsWith( prefix ) ) { proposalList.add( new CompletionProposal( att, offset - prefix.length(), prefix.length(), att.length(), null, null, null, null ) ); } } // attribute descriptions if ( container instanceof LdifContentRecord || container instanceof LdifChangeAddRecord ) { if ( part instanceof LdifInvalidPart || part instanceof LdifAttrValLine || ( part instanceof LdifSepLine && ( container instanceof LdifContentRecord || container instanceof LdifChangeAddRecord ) ) ) { String rawAttributeDescription = prefix; String rawValueType = ""; //$NON-NLS-1$ if ( part instanceof LdifAttrValLine ) { LdifAttrValLine line = ( LdifAttrValLine ) part; rawAttributeDescription = line.getRawAttributeDescription(); rawValueType = line.getRawValueType(); } if ( offset <= part.getOffset() + rawAttributeDescription.length() ) { Schema schema = editor.getConnection() != null ? editor.getConnection().getSchema() : Schema.DEFAULT_SCHEMA; String[] attributeNames = SchemaUtils.getNamesAsArray( schema.getAttributeTypeDescriptions() ); Arrays.sort( attributeNames ); for ( String attributeName : attributeNames ) { if ( rawAttributeDescription.length() == 0 || Strings.toLowerCase( attributeName ).startsWith( Strings.toLowerCase( rawAttributeDescription ) ) ) { String proposal = attributeName; if ( rawValueType.length() == 0 ) { if ( SchemaUtils.isBinary( schema.getAttributeTypeDescription( proposal ), schema ) ) { proposal += ":: "; //$NON-NLS-1$ } else { proposal += ": "; //$NON-NLS-1$ } } proposalList .add( new CompletionProposal( proposal, offset - rawAttributeDescription.length(), rawAttributeDescription.length(), proposal.length() ) ); } } } } } // comment boolean commentOnly = false; if ( documentLineOffset == offset ) { commentOnly = proposalList.isEmpty(); proposalList.add( new CompletionProposal( "# ", offset, 0, 2, LdifEditorActivator.getDefault().getImage( //$NON-NLS-1$ LdifEditorConstants.IMG_LDIF_COMMENT ), "# - Comment", null, null ) ); //$NON-NLS-1$ } // adjust auto-insert this.contentAssistant.enableAutoInsert( !commentOnly ); ICompletionProposal[] proposals = ( ICompletionProposal[] ) proposalList.toArray( new ICompletionProposal[0] ); return proposals; } protected String extractPrefix( ITextViewer viewer, int offset ) { IDocument document = viewer.getDocument(); if ( offset > document.getLength() ) return ""; //$NON-NLS-1$ try { int documentLine = viewer.getDocument().getLineOfOffset( offset ); int documentLineOffset = viewer.getDocument().getLineOffset( documentLine ); String prefix = viewer.getDocument().get( documentLineOffset, offset - documentLineOffset ); return prefix; } catch ( BadLocationException e ) { return ""; //$NON-NLS-1$ } } public IContextInformation[] computeContextInformation( ITextViewer viewer, int offset ) { return null; } public char[] getCompletionProposalAutoActivationCharacters() { char[] chars = new char[53]; for ( int i = 0; i < 26; i++ ) chars[i] = ( char ) ( 'a' + i ); for ( int i = 0; i < 26; i++ ) chars[i + 26] = ( char ) ( 'A' + i ); chars[52] = ':'; return chars; } public char[] getContextInformationAutoActivationCharacters() { return null; } public String getErrorMessage() { return null; } public IContextInformationValidator getContextInformationValidator() { return null; } protected Template[] getTemplates( String contextTypeId ) { Template[] templates = LdifEditorActivator.getDefault().getLdifTemplateStore().getTemplates( contextTypeId ); return templates; } protected TemplateContextType getContextType( ITextViewer viewer, IRegion region ) { int offset = region.getOffset(); LdifFile model = editor.getLdifModel(); LdifContainer container = LdifFile.getContainer( model, offset ); LdifContainer innerContainer = container != null ? LdifFile.getInnerContainer( container, offset ) : null; LdifPart part = container != null ? LdifFile.getContainerContent( container, offset ) : null; int documentLine = -1; int documentLineOffset = -1; String prefix = ""; //$NON-NLS-1$ try { documentLine = viewer.getDocument().getLineOfOffset( offset ); documentLineOffset = viewer.getDocument().getLineOffset( documentLine ); prefix = viewer.getDocument().get( documentLineOffset, offset - documentLineOffset ); } catch ( BadLocationException e ) { } // FILE if ( container == null && innerContainer == null && part == null ) { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_FILE_TEMPLATE_ID ); } if ( container instanceof LdifSepContainer && innerContainer == null && part instanceof LdifSepLine ) { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_FILE_TEMPLATE_ID ); } if ( ( container instanceof LdifInvalidContainer && part instanceof LdifInvalidPart && "d".equals( prefix ) ) //$NON-NLS-1$ || ( container instanceof LdifContentRecord && part instanceof LdifInvalidPart && "dn".equals( prefix ) ) //$NON-NLS-1$ || ( container instanceof LdifContentRecord && part instanceof LdifInvalidPart && "dn:".equals( prefix ) ) ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_FILE_TEMPLATE_ID ); } // MODIFICATION RECORD if ( container instanceof LdifChangeModifyRecord && innerContainer == null && ( part instanceof LdifSepLine || part instanceof LdifInvalidPart ) ) { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_MODIFICATION_RECORD_TEMPLATE_ID ); } // MODIFICATION ITEM if ( container instanceof LdifChangeModifyRecord && innerContainer instanceof LdifModSpec ) { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_MODIFICATION_ITEM_TEMPLATE_ID ); } // MODDN RECORD if ( container instanceof LdifChangeModDnRecord && innerContainer == null && ( part instanceof LdifSepLine || part instanceof LdifInvalidPart ) ) { return LdifEditorActivator.getDefault().getLdifTemplateContextTypeRegistry().getContextType( LdifEditorConstants.LDIF_MODDN_RECORD_TEMPLATE_ID ); } // TemplateContextType contextType = // Activator.getDefault().getContextTypeRegistry().getContextType(LdifEditorConstants.LDIF_FILE_TEMPLATE_ID); // TemplateContextType contextType = // Activator.getDefault().getContextTypeRegistry().getContextType(LdifEditorConstants.LDIF_MODIFICATION_RECORD_TEMPLATE_ID); return null; } protected Image getImage( Template template ) { if ( template.getPattern().indexOf( "add: " ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_ADD ); } else if ( template.getPattern().indexOf( "replace: " ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_REPLACE ); } else if ( template.getPattern().indexOf( "delete: " ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_DELETE ); } else if ( template.getPattern().indexOf( "changetype: add" ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_ADD ); } else if ( template.getPattern().indexOf( "changetype: modify" ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MODIFY ); } else if ( template.getPattern().indexOf( "changetype: delete" ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_DELETE ); } else if ( template.getPattern().indexOf( "changetype: moddn" ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_RENAME ); } else if ( template.getPattern().indexOf( "dn: " ) > -1 ) //$NON-NLS-1$ { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_ENTRY ); } else { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_TEMPLATE ); } } }