/* * 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; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; import org.apache.directory.api.ldap.model.name.Dn; import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator; import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants; import org.apache.directory.studio.ldapbrowser.common.widgets.browser.BrowserLabelProvider; import org.apache.directory.studio.ldapbrowser.core.utils.Utils; import org.apache.directory.studio.ldifeditor.LdifEditorActivator; import org.apache.directory.studio.ldifeditor.LdifEditorConstants; import org.apache.directory.studio.ldifparser.model.LdifFile; import org.apache.directory.studio.ldifparser.model.container.LdifChangeAddRecord; import org.apache.directory.studio.ldifparser.model.container.LdifChangeDeleteRecord; 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.LdifContentRecord; 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.lines.LdifAttrValLine; import org.apache.directory.studio.ldifparser.model.lines.LdifDnLine; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.views.contentoutline.ContentOutlinePage; /** * This class implements the Outline Page for LDIF. * It used to display LDIF files and records. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class LdifOutlinePage extends ContentOutlinePage { /** The editor it is attached to */ private LdifEditor ldifEditor; /** Whether or not the outline page is linked to an entry in the LDAP Browser view*/ private boolean isLinkedToLdapBrowser = false; /** * Creates a new instance of LdifOutlinePage. * * @param ldifEditor * the editor the Outline page is attached to */ public LdifOutlinePage( LdifEditor ldifEditor ) { this.ldifEditor = ldifEditor; } /** * Creates a new instance of LdifOutlinePage. * * @param ldifEditor * the editor the Outline page is attached to */ public LdifOutlinePage( LdifEditor ldifEditor, boolean isLinkedToLdapBrowser ) { this.ldifEditor = ldifEditor; this.isLinkedToLdapBrowser = isLinkedToLdapBrowser; } /** * {@inheritDoc} */ public void createControl( Composite parent ) { super.createControl( parent ); final TreeViewer treeViewer = getTreeViewer(); treeViewer.setLabelProvider( new LdifLabelProvider( ldifEditor, isLinkedToLdapBrowser ) ); treeViewer.setContentProvider( new LdifContentProvider() ); if ( isLinkedToLdapBrowser ) { treeViewer.setAutoExpandLevel( 2 ); } treeViewer.addSelectionChangedListener( new ISelectionChangedListener() { public void selectionChanged( SelectionChangedEvent event ) { if ( !event.getSelection().isEmpty() && event.getSelection() instanceof IStructuredSelection ) { Object element = ( ( IStructuredSelection ) event.getSelection() ).getFirstElement(); if ( element instanceof LdifRecord ) { LdifRecord ldifRecord = ( LdifRecord ) element; ldifEditor.selectAndReveal( ldifRecord.getDnLine().getOffset(), ldifRecord.getDnLine() .getLength() ); } else if ( element instanceof List ) { List<?> list = ( List<?> ) element; if ( !list.isEmpty() && list.get( 0 ) instanceof LdifAttrValLine ) { LdifAttrValLine line = ( LdifAttrValLine ) list.get( 0 ); ldifEditor.selectAndReveal( line.getOffset(), line.getRawAttributeDescription().length() ); } } else if ( element instanceof LdifAttrValLine ) { LdifAttrValLine line = ( LdifAttrValLine ) element; ldifEditor.selectAndReveal( line.getOffset() + line.getRawAttributeDescription().length() + line.getRawValueType().length(), line.getRawValue().length() ); } else if ( element instanceof LdifModSpec ) { LdifModSpec modSpec = ( LdifModSpec ) element; ldifEditor.selectAndReveal( modSpec.getOffset(), modSpec.getModSpecType().getLength() ); } } } } ); treeViewer.addDoubleClickListener( new IDoubleClickListener() { public void doubleClick( DoubleClickEvent event ) { if ( event.getSelection() instanceof IStructuredSelection ) { Object obj = ( ( IStructuredSelection ) event.getSelection() ).getFirstElement(); if ( treeViewer.getExpandedState( obj ) ) treeViewer.collapseToLevel( obj, 1 ); else if ( ( ( ITreeContentProvider ) treeViewer.getContentProvider() ).hasChildren( obj ) ) treeViewer.expandToLevel( obj, 1 ); } } } ); this.refresh(); } /** * Refreshes this viewer starting with the given element. * * @param element * the element */ public void refresh( Object element ) { final TreeViewer treeViewer = getTreeViewer(); if ( treeViewer != null && treeViewer.getTree() != null && !treeViewer.getTree().isDisposed() ) { treeViewer.refresh( element ); } } /** * Refreshes this viewer completely with information freshly obtained from this viewer's model. */ public void refresh() { final TreeViewer treeViewer = getTreeViewer(); if ( treeViewer != null && treeViewer.getTree() != null && !treeViewer.getTree().isDisposed() ) { // ISelection selection = treeViewer.getSelection(); // Object[] expandedElements = treeViewer.getExpandedElements(); if ( !treeViewer.getTree().isEnabled() ) { treeViewer.getTree().setEnabled( true ); } if ( ldifEditor != null ) { if ( treeViewer.getInput() != ldifEditor.getLdifModel() ) { treeViewer.setInput( ldifEditor.getLdifModel() ); } } treeViewer.refresh(); if ( isLinkedToLdapBrowser ) { treeViewer.setAutoExpandLevel( 2 ); } // treeViewer.setSelection(selection); // treeViewer.setExpandedElements(expandedElements); } } /** * {@inheritDoc} */ public void dispose() { super.dispose(); if ( ldifEditor != null ) { ldifEditor.outlinePageClosed(); ldifEditor = null; } } /** * This class implements the ContentProvider used for the LDIF Outline View * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ private static class LdifContentProvider implements ITreeContentProvider { /** * {@inheritDoc} */ public Object[] getChildren( Object element ) { // file --> records if ( element instanceof LdifFile ) { LdifFile ldifFile = ( LdifFile ) element; return ldifFile.getRecords(); } // record --> Array of List of AttrValLine else if ( element instanceof LdifContentRecord ) { LdifContentRecord record = ( LdifContentRecord ) element; return getUniqueAttrValLineArray( record.getAttrVals() ); } else if ( element instanceof LdifChangeAddRecord ) { LdifChangeAddRecord record = ( LdifChangeAddRecord ) element; return getUniqueAttrValLineArray( record.getAttrVals() ); } else if ( element instanceof LdifChangeModifyRecord ) { LdifChangeModifyRecord record = ( LdifChangeModifyRecord ) element; return record.getModSpecs(); } else if ( element instanceof LdifChangeModDnRecord ) { return new Object[0]; } else if ( element instanceof LdifChangeDeleteRecord ) { return new Object[0]; } // List of AttrValLine --> Array of AttrValLine else if ( element instanceof List && ( ( List<?> ) element ).get( 0 ) instanceof LdifAttrValLine ) { List<?> list = ( List<?> ) element; return list.toArray(); } else if ( element instanceof LdifModSpec ) { LdifModSpec modSpec = ( LdifModSpec ) element; return modSpec.getAttrVals(); } else { return new Object[0]; } } /** * Returns a unique line of attribute values from an array of attribute value lines * * @param lines the attribute value lines * @return a unique line of attribute values from an array of attribute values lines */ private Object[] getUniqueAttrValLineArray( LdifAttrValLine[] lines ) { Map<String, List<LdifAttrValLine>> uniqueAttrMap = new LinkedHashMap<String, List<LdifAttrValLine>>(); for ( LdifAttrValLine ldifAttrValLine : lines ) { String key = ldifAttrValLine.getUnfoldedAttributeDescription(); List<LdifAttrValLine> listLdifAttrValLine = uniqueAttrMap.get( key ); if ( listLdifAttrValLine == null ) { listLdifAttrValLine = new ArrayList<LdifAttrValLine>(); uniqueAttrMap.put( key, listLdifAttrValLine ); } listLdifAttrValLine.add( ldifAttrValLine ); } return uniqueAttrMap.values().toArray(); } /** * {@inheritDoc} */ public Object getParent( Object element ) { return null; } /** * {@inheritDoc} */ public boolean hasChildren( Object element ) { return getChildren( element ) != null && getChildren( element ).length > 0; } /** * {@inheritDoc} */ public Object[] getElements( Object inputElement ) { return getChildren( inputElement ); } /** * {@inheritDoc} */ public void dispose() { } /** * {@inheritDoc} */ public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { } } /** * This class implements the LabelProvider used for the LDIF Outline View * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ private static class LdifLabelProvider extends LabelProvider { /** The editor it is attached to */ private LdifEditor ldifEditor; /** Whether or not the outline page is linked to an entry in the LDAP Browser view*/ private boolean isLinkedToLdapBrowser = false; public LdifLabelProvider( LdifEditor ldifEditor, boolean isLinkedToLdapBrowser ) { super(); this.ldifEditor = ldifEditor; this.isLinkedToLdapBrowser = isLinkedToLdapBrowser; } /** * {@inheritDoc} */ public String getText( Object element ) { // Record if ( element instanceof LdifRecord ) { LdifRecord ldifRecord = ( LdifRecord ) element; return ldifRecord.getDnLine().getValueAsString(); } // List of AttrValLine else if ( element instanceof List && ( ( List<?> ) element ).get( 0 ) instanceof LdifAttrValLine ) { List<?> list = ( List<?> ) element; return ( ( LdifAttrValLine ) list.get( 0 ) ).getUnfoldedAttributeDescription() + " (" + list.size() //$NON-NLS-1$ + ")"; //$NON-NLS-1$ } else if ( element instanceof LdifModSpec ) { LdifModSpec modSpec = ( LdifModSpec ) element; return modSpec.getModSpecType().getUnfoldedAttributeDescription() + " (" + modSpec.getAttrVals().length //$NON-NLS-1$ + ")"; //$NON-NLS-1$ } // AttrValLine else if ( element instanceof LdifAttrValLine ) { LdifAttrValLine line = ( LdifAttrValLine ) element; return Utils.getShortenedString( line.getValueAsString(), 20 ); } else { return ""; //$NON-NLS-1$ } } /** * {@inheritDoc} */ public Image getImage( Object element ) { // Record if ( element instanceof LdifContentRecord ) { if ( isLinkedToLdapBrowser ) { LdifContentRecord record = ( LdifContentRecord ) element; LdifDnLine dnLine = record.getDnLine(); if ( dnLine != null ) { String dn = dnLine.getUnfoldedDn(); if ( ( dn != null ) && ( dn.length() == 0 ) ) //$NON-NLS-1$ { // Root DSE return BrowserCommonActivator.getDefault().getImage( BrowserCommonConstants.IMG_ENTRY_ROOT ); } else { // Any other case try { return BrowserLabelProvider.getImageByObjectClass( ldifEditor.getConnection() .getEntryFromCache( new Dn( dn ) ) ); } catch ( LdapInvalidDnException e ) { // Will never occur } } } } return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_ENTRY ); } else if ( element instanceof LdifChangeAddRecord ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_ADD ); } else if ( element instanceof LdifChangeModifyRecord ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MODIFY ); } else if ( element instanceof LdifChangeDeleteRecord ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_DELETE ); } else if ( element instanceof LdifChangeModDnRecord ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_RENAME ); } // List of AttrValLine else if ( element instanceof List && ( ( List ) element ).get( 0 ) instanceof LdifAttrValLine ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_ATTRIBUTE ); } else if ( element instanceof LdifModSpec ) { LdifModSpec modSpec = ( LdifModSpec ) element; if ( modSpec.isAdd() ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_ADD ); } else if ( modSpec.isReplace() ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_REPLACE ); } else if ( modSpec.isDelete() ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_MOD_DELETE ); } else { return null; } } // AttrValLine else if ( element instanceof LdifAttrValLine ) { return LdifEditorActivator.getDefault().getImage( LdifEditorConstants.IMG_LDIF_VALUE ); } else { return null; } } } }