KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > directory > ldapstudio > ldifeditor > editor > LdifDocumentProvider


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  *
19  */

20
21 package org.apache.directory.ldapstudio.ldifeditor.editor;
22
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.BufferedWriter JavaDoc;
26 import java.io.File JavaDoc;
27 import java.io.FileNotFoundException JavaDoc;
28 import java.io.FileReader JavaDoc;
29 import java.io.FileWriter JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.Reader JavaDoc;
32 import java.io.Writer JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.List JavaDoc;
35
36 import org.apache.directory.ldapstudio.browser.core.BrowserCoreConstants;
37 import org.apache.directory.ldapstudio.browser.core.model.ldif.LdifFile;
38 import org.apache.directory.ldapstudio.browser.core.model.ldif.container.LdifContainer;
39 import org.apache.directory.ldapstudio.browser.core.model.ldif.container.LdifRecord;
40 import org.apache.directory.ldapstudio.browser.core.model.ldif.parser.LdifParser;
41 import org.apache.directory.ldapstudio.ldifeditor.LdifEditorActivator;
42 import org.apache.directory.ldapstudio.ldifeditor.editor.text.LdifExternalAnnotationModel;
43 import org.eclipse.core.runtime.CoreException;
44 import org.eclipse.core.runtime.IPath;
45 import org.eclipse.core.runtime.IProgressMonitor;
46 import org.eclipse.core.runtime.IStatus;
47 import org.eclipse.core.runtime.Status;
48 import org.eclipse.jface.operation.IRunnableContext;
49 import org.eclipse.jface.text.Document;
50 import org.eclipse.jface.text.DocumentEvent;
51 import org.eclipse.jface.text.IDocument;
52 import org.eclipse.jface.text.IDocumentListener;
53 import org.eclipse.jface.text.Region;
54 import org.eclipse.jface.text.TextUtilities;
55 import org.eclipse.jface.text.source.IAnnotationModel;
56 import org.eclipse.ui.IEditorInput;
57 import org.eclipse.ui.IPathEditorInput;
58 import org.eclipse.ui.texteditor.AbstractDocumentProvider;
59
60
61 /**
62  * This class implements the LDIF Document Provider.
63  * This class is used to share a LDIF Document and listen on document modifications.
64  *
65  * @author <a HREF="mailto:dev@directory.apache.org">Apache Directory Project</a>
66  * @version $Rev$, $Date$
67  */

68 public class LdifDocumentProvider extends AbstractDocumentProvider implements IDocumentListener
69 {
70
71     private final LdifParser ldifParser;
72
73     private final LdifDocumentSetupParticipant ldifDocumentSetupParticipant;
74
75     private LdifFile ldifModel;
76
77
78     /**
79      * Creates a new instance of LdifDocumentProvider.
80      */

81     public LdifDocumentProvider()
82     {
83         super();
84         this.ldifParser = new LdifParser();
85         this.ldifDocumentSetupParticipant = new LdifDocumentSetupParticipant();
86     }
87
88
89     /**
90      * {@inheritDoc}
91      */

92     public IDocument getDocument( Object JavaDoc element )
93     {
94         IDocument document = super.getDocument( element );
95         return document;
96     }
97
98
99     /**
100      * Gets the LDIF Model
101      *
102      * @return
103      * the LDIF Model
104      */

105     public LdifFile getLdifModel()
106     {
107         return ldifModel;
108     }
109
110
111     /**
112      * {@inheritDoc}
113      */

114     public void documentAboutToBeChanged( DocumentEvent event )
115     {
116     }
117
118
119     /**
120      * Update the LDIF Model.
121      */

122     public void documentChanged( DocumentEvent event )
123     {
124         try
125         {
126             int changeOffset = event.getOffset();
127             int replacedTextLength = event.getLength();
128             int insertedTextLength = event.getText() != null ? event.getText().length() : 0;
129             IDocument document = event.getDocument();
130             // Region changeRegion = new Region(changeOffset,
131
// replacedTextLength);
132
Region changeRegion = new Region( changeOffset - BrowserCoreConstants.LINE_SEPARATOR.length(),
133                 replacedTextLength + ( 2 * BrowserCoreConstants.LINE_SEPARATOR.length() ) );
134
135             // get containers to replace (from changeOffset till
136
// changeOffset+replacedTextLength, check end of record)
137
List JavaDoc<LdifContainer> oldContainerList = new ArrayList JavaDoc<LdifContainer>();
138             LdifContainer[] containers = this.ldifModel.getContainers();
139             for ( int i = 0; i < containers.length; i++ )
140             {
141
142                 Region containerRegion = new Region( containers[i].getOffset(), containers[i].getLength() );
143
144                 boolean changeOffsetAtEOF = i == containers.length - 1
145                     && changeOffset >= containerRegion.getOffset() + containerRegion.getLength();
146
147                 if ( TextUtilities.overlaps( containerRegion, changeRegion ) || changeOffsetAtEOF )
148                 {
149
150                     // remember index
151
int index = i;
152
153                     // add invalid containers and non-records before overlap
154
i--;
155                     for ( ; i >= 0; i-- )
156                     {
157                         if ( !containers[i].isValid() || !( containers[i] instanceof LdifRecord ) )
158                         {
159                             oldContainerList.add( 0, containers[i] );
160                         }
161                         else
162                         {
163                             break;
164                         }
165                     }
166
167                     // add all overlapping containers
168
i = index;
169                     for ( ; i < containers.length; i++ )
170                     {
171                         containerRegion = new Region( containers[i].getOffset(), containers[i].getLength() );
172                         if ( TextUtilities.overlaps( containerRegion, changeRegion ) || changeOffsetAtEOF )
173                         {
174                             oldContainerList.add( containers[i] );
175                         }
176                         else
177                         {
178                             break;
179                         }
180                     }
181
182                     // add invalid containers and non-records after overlap
183
for ( ; i < containers.length; i++ )
184                     {
185                         if ( !containers[i].isValid() || !( containers[i] instanceof LdifRecord )
186                             || !( oldContainerList.get( oldContainerList.size() - 1 ) instanceof LdifRecord ) )
187                         {
188                             oldContainerList.add( containers[i] );
189                         }
190                         else
191                         {
192                             break;
193                         }
194                     }
195                 }
196             }
197             LdifContainer[] oldContainers = ( LdifContainer[] ) oldContainerList
198                 .toArray( new LdifContainer[oldContainerList.size()] );
199             int oldCount = oldContainers.length;
200             int oldOffset = oldCount > 0 ? oldContainers[0].getOffset() : 0;
201             int oldLength = oldCount > 0 ? ( oldContainers[oldContainers.length - 1].getOffset()
202                 + oldContainers[oldContainers.length - 1].getLength() - oldContainers[0].getOffset() ) : 0;
203
204             // get new content
205
int newOffset = oldOffset;
206             int newLength = oldLength - replacedTextLength + insertedTextLength;
207             String JavaDoc textToParse = document.get( newOffset, newLength );
208
209             // parse partion content to containers (offset=0)
210
LdifFile newModel = this.ldifParser.parse( textToParse );
211             LdifContainer[] newContainers = newModel.getContainers();
212
213             // replace old containers with new containers
214
// must adjust offsets of all following containers in model
215
this.ldifModel.replace( oldContainers, newContainers );
216
217         }
218         catch ( Exception JavaDoc e )
219         {
220             e.printStackTrace();
221         }
222
223     }
224
225
226     /**
227      * Creates an LDIF annotation model.
228      */

229     protected IAnnotationModel createAnnotationModel( Object JavaDoc element ) throws CoreException
230     {
231         return new LdifExternalAnnotationModel();
232     }
233
234
235     /**
236      * Tries to read the file pointed at by <code>input</code> if it is an
237      * <code>IPathEditorInput</code>. If the file does not exist, <code>true</code>
238      * is returned.
239      *
240      * @param document the document to fill with the contents of <code>input</code>
241      * @param input the editor input
242      * @return <code>true</code> if setting the content was successful or no file exists, <code>false</code> otherwise
243      * @throws CoreException if reading the file fails
244      */

245     private boolean setDocumentContent( IDocument document, IEditorInput input ) throws CoreException
246     {
247         // TODO: handle encoding
248
Reader JavaDoc reader;
249         try
250         {
251             if ( input instanceof IPathEditorInput )
252             {
253                 reader = new FileReader JavaDoc( ( ( IPathEditorInput ) input ).getPath().toFile() );
254             }
255             else
256             {
257                 return false;
258             }
259         }
260         catch ( FileNotFoundException JavaDoc e )
261         {
262             // return empty document and save later
263
return true;
264         }
265
266         try
267         {
268             setDocumentContent( document, reader );
269             return true;
270         }
271         catch ( IOException JavaDoc e )
272         {
273             throw new CoreException( new Status( IStatus.ERROR, LdifEditorActivator.PLUGIN_ID, IStatus.OK,
274                 "error reading file", e ) ); //$NON-NLS-1$
275
}
276     }
277
278
279     /**
280      * Reads in document content from a reader and fills <code>document</code>
281      *
282      * @param document the document to fill
283      * @param reader the source
284      * @throws IOException if reading fails
285      */

286     private void setDocumentContent( IDocument document, Reader JavaDoc reader ) throws IOException JavaDoc
287     {
288         Reader JavaDoc in = new BufferedReader JavaDoc( reader );
289         try
290         {
291             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc( 512 );
292             char[] readBuffer = new char[512];
293             int n = in.read( readBuffer );
294             while ( n > 0 )
295             {
296                 buffer.append( readBuffer, 0, n );
297                 n = in.read( readBuffer );
298             }
299
300             document.set( buffer.toString() );
301
302         }
303         finally
304         {
305             in.close();
306         }
307     }
308
309
310     /**
311      * Set up the document: partitioning and incremental parser
312      *
313      * @param document the new document
314      */

315     private void setupDocument( IDocument document )
316     {
317
318         // setup document partitioning
319
ldifDocumentSetupParticipant.setup( document );
320
321         // initial parsing of whole document
322
this.ldifModel = this.ldifParser.parse( document.get() );
323
324         // add listener for incremental parsing
325
document.addDocumentListener( this );
326
327     }
328
329
330     /**
331      * Remove document listener.
332      */

333     protected void disposeElementInfo( Object JavaDoc element, ElementInfo info )
334     {
335         IDocument document = info.fDocument;
336         document.removeDocumentListener( this );
337
338         super.disposeElementInfo( element, info );
339     }
340
341
342     /**
343      * {@inheritDoc}
344      */

345     protected IDocument createDocument( Object JavaDoc element ) throws CoreException
346     {
347         if ( element instanceof IEditorInput )
348         {
349             IDocument document = new Document();
350             if ( setDocumentContent( document, ( IEditorInput ) element ) )
351             {
352                 setupDocument( document );
353             }
354             return document;
355         }
356
357         return null;
358     }
359
360
361     /**
362      * {@inheritDoc}
363      */

364     protected void doSaveDocument( IProgressMonitor monitor, Object JavaDoc element, IDocument document, boolean overwrite )
365         throws CoreException
366     {
367
368         if ( element instanceof IPathEditorInput )
369         {
370             IPathEditorInput pei = ( IPathEditorInput ) element;
371             IPath path = pei.getPath();
372             File JavaDoc file = path.toFile();
373
374             try
375             {
376                 file.createNewFile();
377
378                 if ( file.exists() )
379                 {
380                     if ( file.canWrite() )
381                     {
382                         Writer JavaDoc writer = new FileWriter JavaDoc( file );
383                         writeDocumentContent( document, writer, monitor );
384                     }
385                     else
386                     {
387                         throw new CoreException( new Status( IStatus.ERROR,
388                             "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "file is read-only", null ) ); //$NON-NLS-1$ //$NON-NLS-2$
389
}
390                 }
391                 else
392                 {
393                     throw new CoreException( new Status( IStatus.ERROR,
394                         "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "error creating file", null ) ); //$NON-NLS-1$ //$NON-NLS-2$
395
}
396             }
397             catch ( IOException JavaDoc e )
398             {
399                 throw new CoreException( new Status( IStatus.ERROR,
400                     "org.eclipse.ui.examples.rcp.texteditor", IStatus.OK, "error when saving file", e ) ); //$NON-NLS-1$ //$NON-NLS-2$
401
}
402
403         }
404     }
405
406
407     /**
408      * Saves the document contents to a stream.
409      *
410      * @param document the document to save
411      * @param writer the stream to save it to
412      * @param monitor a progress monitor to report progress
413      * @throws IOException if writing fails
414      */

415     private void writeDocumentContent( IDocument document, Writer JavaDoc writer, IProgressMonitor monitor ) throws IOException JavaDoc
416     {
417         Writer JavaDoc out = new BufferedWriter JavaDoc( writer );
418         try
419         {
420             out.write( document.get() );
421         }
422         finally
423         {
424             out.close();
425         }
426     }
427
428
429     /**
430      * {@inheritDoc}
431      */

432     protected IRunnableContext getOperationRunner( IProgressMonitor monitor )
433     {
434         return null;
435     }
436
437
438     /**
439      * {@inheritDoc}
440      */

441     public boolean isModifiable( Object JavaDoc element )
442     {
443         if ( element instanceof IPathEditorInput )
444         {
445             IPathEditorInput pei = ( IPathEditorInput ) element;
446             File JavaDoc file = pei.getPath().toFile();
447             return file.canWrite() || !file.exists(); // Allow to edit new files
448
}
449         return false;
450     }
451
452
453     /**
454      * {@inheritDoc}
455      */

456     public boolean isReadOnly( Object JavaDoc element )
457     {
458         return !isModifiable( element );
459     }
460
461
462     /**
463      * {@inheritDoc}
464      */

465     public boolean isStateValidated( Object JavaDoc element )
466     {
467         return true;
468     }
469 }
Popular Tags