Source Code Cross Referenced for FormRefactoringUpdate.java in  » IDE-Netbeans » form » org » netbeans » modules » form » 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 Netbeans » form » org.netbeans.modules.form 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:         *
004:         * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:         *
006:         * The contents of this file are subject to the terms of either the GNU
007:         * General Public License Version 2 only ("GPL") or the Common
008:         * Development and Distribution License("CDDL") (collectively, the
009:         * "License"). You may not use this file except in compliance with the
010:         * License. You can obtain a copy of the License at
011:         * http://www.netbeans.org/cddl-gplv2.html
012:         * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013:         * specific language governing permissions and limitations under the
014:         * License.  When distributing the software, include this License Header
015:         * Notice in each file and include the License file at
016:         * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
017:         * particular file as subject to the "Classpath" exception as provided
018:         * by Sun in the GPL Version 2 section of the License file that
019:         * accompanied this code. If applicable, add the following below the
020:         * License Header, with the fields enclosed by brackets [] replaced by
021:         * your own identifying information:
022:         * "Portions Copyrighted [year] [name of copyright owner]"
023:         *
024:         * Contributor(s):
025:         *
026:         * The Original Software is NetBeans. The Initial Developer of the Original
027:         * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028:         * Microsystems, Inc. All Rights Reserved.
029:         *
030:         * If you wish your version of this file to be governed by only the CDDL
031:         * or only the GPL Version 2, indicate your decision by adding
032:         * "[Contributor] elects to include this software in this distribution
033:         * under the [CDDL or GPL Version 2] license." If you do not indicate a
034:         * single choice of license, a recipient has the option to distribute
035:         * your version of this file under either the CDDL, the GPL Version 2 or
036:         * to extend the choice of license to its licensees as provided above.
037:         * However, if you add GPL Version 2 code and therefore, elected the GPL
038:         * Version 2 license, then the option applies only if the new code is
039:         * made subject to such option by the copyright holder.
040:         */
041:        package org.netbeans.modules.form;
042:
043:        import java.awt.EventQueue;
044:        import java.io.BufferedReader;
045:        import java.io.IOException;
046:        import java.io.InputStream;
047:        import java.io.InputStreamReader;
048:        import java.io.OutputStream;
049:        import java.net.URL;
050:        import java.util.ArrayList;
051:        import java.util.LinkedList;
052:        import java.util.List;
053:        import org.netbeans.api.java.classpath.ClassPath;
054:        import org.netbeans.modules.refactoring.spi.BackupFacility;
055:        import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
056:        import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
057:        import org.netbeans.modules.refactoring.spi.Transaction;
058:        import org.openide.filesystems.FileLock;
059:        import org.openide.filesystems.FileObject;
060:        import org.openide.filesystems.URLMapper;
061:        import org.openide.loaders.DataObject;
062:        import org.openide.loaders.DataObjectNotFoundException;
063:        import org.openide.text.PositionBounds;
064:        import org.openide.util.Exceptions;
065:        import org.openide.util.Lookup;
066:        import org.openide.util.NbBundle;
067:
068:        /**
069:         * This class does the actual refactoring changes for one form - updates the
070:         * form, regenerates code, updates properties files for i18n, etc. Multiple
071:         * different instances (updates) can be created and executed for one refactoring
072:         * (all kept in RefacoringInfo).
073:         * 
074:         * @author Tomas Pavek
075:         */
076:        public class FormRefactoringUpdate extends
077:                SimpleRefactoringElementImplementation implements  Transaction {
078:
079:            /**
080:             * Information about the performed refactoring.
081:             */
082:            private RefactoringInfo refInfo;
083:
084:            /**
085:             * RefactoringElement used in the preview, but doing nothing.
086:             */
087:            private RefactoringElementImplementation previewElement;
088:
089:            /**
090:             * Java file of a form affected by the refactoring.
091:             */
092:            private FileObject changingFile;
093:
094:            /**
095:             * DataObject of the changed file. Has changedFile as primary file at the
096:             * beginning, but may get a different one later (e.g. if moved).
097:             */
098:            private FormDataObject formDataObject;
099:
100:            /**
101:             * FormEditor of the updated form. Either taken from the FormDataObject
102:             * (typically when already opened), or created temporarily just to do the
103:             * update. See prepareForm method.
104:             */
105:            private FormEditor formEditor;
106:
107:            private boolean loadingFailed;
108:
109:            /**
110:             * Whether a change in guarded code was requested by java refactoring.
111:             */
112:            private boolean guardedCodeChanging;
113:
114:            private boolean transactionDone;
115:
116:            private boolean formFileRenameDone;
117:
118:            private List<RefactoringElementImplementation> preFileChanges;
119:
120:            private List<BackupFacility.Handle> backups;
121:
122:            // -----
123:
124:            public FormRefactoringUpdate(RefactoringInfo refInfo,
125:                    FileObject changingFile) {
126:                this .refInfo = refInfo;
127:                this .changingFile = changingFile;
128:                try {
129:                    DataObject dobj = DataObject.find(changingFile);
130:                    if (dobj instanceof  FormDataObject) {
131:                        formDataObject = (FormDataObject) dobj;
132:                    }
133:                } catch (DataObjectNotFoundException ex) {
134:                    assert false;
135:                }
136:            }
137:
138:            FormDataObject getFormDataObject() {
139:                return formDataObject;
140:            }
141:
142:            RefactoringElementImplementation getPreviewElement(/*String displayText*/) {
143:                if (previewElement == null) {
144:                    previewElement = new PreviewElement(changingFile/*, displayText*/);
145:                }
146:                return previewElement;
147:            }
148:
149:            void setGaurdedCodeChanging(boolean b) {
150:                guardedCodeChanging = b;
151:            }
152:
153:            boolean isGuardedCodeChanging() {
154:                return guardedCodeChanging;
155:            }
156:
157:            public void addPrecedingFileChange(
158:                    RefactoringElementImplementation change) {
159:                if (preFileChanges == null) {
160:                    preFileChanges = new LinkedList<RefactoringElementImplementation>();
161:                }
162:                preFileChanges.add(change);
163:            }
164:
165:            // -----
166:
167:            // Transaction (registered via RefactoringElementsBag.registerTransaction)
168:            public void commit() {
169:                if (previewElement != null && !previewElement.isEnabled()) {
170:                    return;
171:                }
172:
173:                // As "transactions" we do updates for changes affecting only the
174:                // content of the source file, not changing the file's name or location.
175:                // Our transaction is called after retouche commits its changes to the
176:                // source. After all transactions are done, the source file is saved
177:                // automatically.
178:
179:                switch (refInfo.getChangeType()) {
180:                case VARIABLE_RENAME:
181:                    renameMetaComponent(refInfo.getOldName(), refInfo
182:                            .getNewName());
183:                    transactionDone = true;
184:                    break;
185:                case CLASS_RENAME: // renaming a component class used in the form
186:                    if (!refInfo.getPrimaryFile().equals(changingFile)) {
187:                        componentClassRename(refInfo.getOldName(), refInfo
188:                                .getNewName());
189:                        transactionDone = true;
190:                    }
191:                    break;
192:                case CLASS_MOVE: // moving a component class used in the form
193:                    if (!refInfo.getPrimaryFile().equals(changingFile)) {
194:                        componentChange(refInfo.getOldName(), refInfo
195:                                .getNewName());
196:                        transactionDone = true;
197:                    }
198:                    break;
199:                //do nothing otherwise - could be just redundantly registered by the guarded handler
200:                case CLASS_DELETE: // deleting form (we only need to backup the form file for undo)
201:                    saveFormForUndo();
202:                    transactionDone = true;
203:                    break;
204:                }
205:
206:            }
207:
208:            // Transaction (registered via RefactoringElementsBag.registerTransaction)
209:            public void rollback() {
210:                if (previewElement != null && !previewElement.isEnabled()) {
211:                    return;
212:                }
213:                undoFromBackups();
214:                /*        switch (refInfo.getChangeType()) {
215:                 case VARIABLE_RENAME:
216:                 renameMetaComponent(refInfo.getNewName(), refInfo.getOldName());
217:                 break;
218:                 case CLASS_RENAME: // renaming a component class used in the form
219:                 if (!refInfo.getPrimaryFile().equals(changingFile)) {
220:                 componentClassRename(refInfo.getNewName(), refInfo.getOldName());
221:                 }
222:                 break;
223:                 case CLASS_MOVE: // moving a component class used in the form
224:                 if (!refInfo.getPrimaryFile().equals(changingFile)) {
225:                 componentChange(refInfo.getNewName(), refInfo.getOldName());
226:                 }
227:                 break;
228:                 } */
229:            }
230:
231:            // RefactoringElementImplementation (registered via RefactoringElementsBag.addFileChange)
232:            public void performChange() {
233:                if (previewElement != null && !previewElement.isEnabled()) {
234:                    return;
235:                }
236:                if (transactionDone) { // could be registered redundantly as file change
237:                    processCustomCode();
238:                    return;
239:                }
240:
241:                // As "file changes" we do updates that react on changes of the source
242:                // file's name or location. We need the source file to be already
243:                // renamed/moved. The file changes are run after the "transactions".
244:
245:                if (preFileChanges != null) {
246:                    for (RefactoringElementImplementation change : preFileChanges) {
247:                        change.performChange();
248:                    }
249:                }
250:
251:                switch (refInfo.getChangeType()) {
252:                case CLASS_RENAME: // renaming the form itself
253:                    if (refInfo.getPrimaryFile().equals(changingFile)) {
254:                        formRename();
255:                    }
256:                    break;
257:                case CLASS_MOVE: // moving the form itself
258:                    if (refInfo.getPrimaryFile().equals(changingFile)
259:                            && prepareForm(false)) {
260:                        formMove();
261:                    }
262:                    break;
263:                case PACKAGE_RENAME:
264:                case FOLDER_RENAME:
265:                    packageRename();
266:                    break;
267:                }
268:
269:                processCustomCode();
270:            }
271:
272:            // RefactoringElementImplementation (registered via RefactoringElementsBag.addFileChange)
273:            @Override
274:            public void undoChange() {
275:                if (previewElement != null && !previewElement.isEnabled()) {
276:                    return;
277:                }
278:                if (transactionDone) { // could be registered redundantly as file change
279:                    return;
280:                }
281:
282:                undoFromBackups();
283:
284:                if (preFileChanges != null) {
285:                    for (RefactoringElementImplementation change : preFileChanges) {
286:                        change.undoChange();
287:                    }
288:                }
289:            }
290:
291:            // -----
292:
293:            private void renameMetaComponent(String oldName, String newName) {
294:                if (prepareForm(true)) {
295:                    RADComponent metacomp = formEditor.getFormModel()
296:                            .findRADComponent(oldName);
297:                    if (metacomp != null) {
298:                        saveFormForUndo();
299:                        saveResourcesForContentChangeUndo();
300:                        metacomp.setName(newName);
301:                        updateForm(false);
302:                    }
303:                }
304:            }
305:
306:            private void formRename(/*boolean saveAll*/) {
307:                if (prepareForm(true)) {
308:                    saveFormForUndo();
309:                    saveResourcesForFormRenameUndo();
310:                    ResourceSupport.formRenamed(formEditor.getFormModel(),
311:                            refInfo.getOldName());
312:                    updateForm(true);
313:                }
314:            }
315:
316:            private void componentClassRename(String oldName, String newName) {
317:                FileObject renamedFile = refInfo.getPrimaryFile();
318:                String pkg = ClassPath.getClassPath(renamedFile,
319:                        ClassPath.SOURCE).getResourceName(
320:                        renamedFile.getParent(), '.', false);
321:                String oldClassName = (pkg != null && pkg.length() > 0) ? pkg
322:                        + "." + oldName : oldName; // NOI18N
323:                String newClassName = (pkg != null && pkg.length() > 0) ? pkg
324:                        + "." + newName : newName; // NOI18N
325:                componentChange(oldClassName, newClassName);
326:            }
327:
328:            private void formMove(/*final boolean saveAll*/) {
329:                final FormEditorSupport fes = formDataObject
330:                        .getFormEditorSupport();
331:                if (fes.isOpened()) {
332:                    EventQueue.invokeLater(new Runnable() {
333:                        public void run() {
334:                            formEditor = fes.reloadFormEditor();
335:                            formMove2(/*saveAll*/);
336:                        }
337:                    });
338:                } else {
339:                    assert !formEditor.isFormLoaded();
340:                    formMove2(/*saveAll*/);
341:                }
342:            }
343:
344:            private void formMove2(/*boolean saveAll*/) {
345:                if (prepareForm(true)) {
346:                    saveFormForUndo();
347:                    FileObject oldFolder = changingFile.getParent();
348:                    saveResourcesForFormMoveUndo(oldFolder);
349:                    ResourceSupport.formMoved(formEditor.getFormModel(),
350:                            oldFolder);
351:                    updateForm(true);
352:                }
353:            }
354:
355:            private void componentChange(String oldClassName,
356:                    String newClassName) {
357:                FormEditorSupport fes = formDataObject.getFormEditorSupport();
358:                if (fes.isOpened()) {
359:                    fes.closeFormEditor();
360:                }
361:                replaceClassOrPkgName(oldClassName, newClassName, false);
362:                replaceShortClassName(oldClassName, newClassName);
363:            }
364:
365:            private boolean replaceShortClassName(String oldName, String newName) {
366:                if (oldName.contains(".")) { // NOI18N
367:                    String shortOldName = oldName.substring(oldName
368:                            .lastIndexOf('.') + 1);
369:                    String shortNewName = newName.substring(newName
370:                            .lastIndexOf('.') + 1);
371:                    if (!shortNewName.equals(shortOldName)) {
372:                        return replaceClassOrPkgName(shortOldName, newName,
373:                                false); // (intentionally replace with FQN)
374:                    }
375:                }
376:                return false;
377:            }
378:
379:            private void packageRename() {
380:                FormEditorSupport fes = formDataObject.getFormEditorSupport();
381:                if (fes.isOpened()) {
382:                    fes.closeFormEditor();
383:                }
384:                if (replaceClassOrPkgName(refInfo.getOldName(), refInfo
385:                        .getNewName(), true)
386:                        && !isGuardedCodeChanging()) {
387:                    // some package references in resource were changed in the form file
388:                    // (not class names since no change in guarded code came from java
389:                    // refactoring) and because no component has changed we can load the
390:                    // form and regenerate to get the new resource names into code
391:                    updateForm(true);
392:                }
393:            }
394:
395:            /**
396:             * Tries to update the fragments of custom code in the .form file according
397:             * to the refactoring change. The implementation is quite simple and 
398:             * super-ugly. It goes through the form file, finds relevant attributes,
399:             * and blindly replaces given "old name" with a "new name". Should mostly
400:             * work when a component variable or class is renamed. Should be enough
401:             * though, since the usage of custom code is quite limited.
402:             */
403:            private void processCustomCode() {
404:                if (isGuardedCodeChanging() && !formFileRenameDone) {
405:                    String oldName = refInfo.getOldName();
406:                    String newName = refInfo.getNewName();
407:                    if (oldName != null && newName != null) {
408:                        boolean replaced = replaceClassOrPkgName(oldName,
409:                                newName, false);
410:                        // also try to replace short class name
411:                        switch (refInfo.getChangeType()) {
412:                        case CLASS_RENAME:
413:                        case CLASS_MOVE:
414:                            replaced |= replaceShortClassName(oldName, newName);
415:                            break;
416:                        }
417:                        if (replaced) { // regenerate the code
418:                            // need to reload the form from file
419:                            final FormEditorSupport fes = formDataObject
420:                                    .getFormEditorSupport();
421:                            if (fes.isOpened()) {
422:                                EventQueue.invokeLater(new Runnable() {
423:                                    public void run() {
424:                                        formEditor = fes.reloadFormEditor();
425:                                        updateForm(true);
426:                                    }
427:                                });
428:                            } else {
429:                                if (formEditor != null
430:                                        && formEditor.isFormLoaded()) {
431:                                    formEditor.closeForm();
432:                                }
433:                                if (prepareForm(true)) {
434:                                    updateForm(true);
435:                                }
436:                            }
437:                        }
438:                        formFileRenameDone = false; // not to block redo
439:                    }
440:                }
441:            }
442:
443:            // -----
444:
445:            /**
446:             * Regenerate code and save.
447:             */
448:            private void updateForm(boolean saveAll) {
449:                if (!prepareForm(true)) {
450:                    return;
451:                }
452:                // hack: regenerate code immediately
453:                formEditor.getFormModel().fireFormChanged(true);
454:                FormEditorSupport fes = getFormDataObject()
455:                        .getFormEditorSupport();
456:                try {
457:                    if (!fes.isOpened()) {
458:                        // the form is not opened, just loaded aside to do this refactoring
459:                        // update (not held from FormEditorSupport); so we must save the
460:                        // form always - it would not get save with refactoring
461:                        formEditor.saveFormData(); // TODO should save form only if there was a change
462:                        if (saveAll) { // a post-refactoring change that would not be saved by refactoring
463:                            fes.saveSourceOnly();
464:                        }
465:                        formEditor.closeForm();
466:                    } else if (saveAll) { // a post-refactoring change that would not be saved
467:                        fes.saveDocument();
468:                    }
469:                } catch (Exception ex) {
470:                    Exceptions.printStackTrace(ex);
471:                }
472:            }
473:
474:            boolean prepareForm(boolean load) {
475:                if (formDataObject != null) {
476:                    FormEditor fe = formDataObject.getFormEditorSupport()
477:                            .getFormEditor();
478:                    if (fe != null) { // use the current FormEditor (might change due to reload after undo)
479:                        formEditor = fe;
480:                    } else if (formEditor == null) { // create a disconnected form editor
481:                        formEditor = new FormEditor(formDataObject);
482:                    }
483:                }
484:                if (formEditor != null) {
485:                    if (formEditor.isFormLoaded() || !load) {
486:                        return true;
487:                    } else if (!loadingFailed) {
488:                        if (formEditor.loadForm()) {
489:                            return true;
490:                        } else {
491:                            loadingFailed = true;
492:                        }
493:                    }
494:                }
495:                return false;
496:            }
497:
498:            private void saveFormForUndo() {
499:                saveForUndo(formDataObject.getFormFile());
500:                // java file is backed up by java refactoring
501:            }
502:
503:            private void saveResourcesForContentChangeUndo() {
504:                for (URL url : ResourceSupport
505:                        .getFilesForContentChangeBackup(formEditor
506:                                .getFormModel())) {
507:                    saveForUndo(url);
508:                }
509:            }
510:
511:            private void saveResourcesForFormRenameUndo() {
512:                for (URL url : ResourceSupport
513:                        .getFilesForFormRenameBackup(formEditor.getFormModel())) {
514:                    saveForUndo(url);
515:                }
516:            }
517:
518:            private void saveResourcesForFormMoveUndo(FileObject oldFolder) {
519:                for (URL url : ResourceSupport.getFilesForFormMoveBackup(
520:                        formEditor.getFormModel(), oldFolder)) {
521:                    saveForUndo(url);
522:                }
523:            }
524:
525:            private void saveForUndo(final URL url) {
526:                FileObject file = URLMapper.findFileObject(url);
527:                BackupFacility.Handle id;
528:                if (file != null) {
529:                    try {
530:                        id = BackupFacility.getDefault().backup(file);
531:                    } catch (IOException ex) {
532:                        Exceptions.printStackTrace(ex);
533:                        return;
534:                    }
535:                } else { // file does not exist - will be created; to undo we must delete it
536:                    id = new BackupFacility.Handle() {
537:                        public void restore() throws IOException {
538:                            FileObject file = URLMapper.findFileObject(url);
539:                            if (file != null) {
540:                                file.delete();
541:                            }
542:                        }
543:                    };
544:                }
545:                if (backups == null) {
546:                    backups = new ArrayList<BackupFacility.Handle>();
547:                }
548:                backups.add(id);
549:            }
550:
551:            private void saveForUndo(FileObject file) {
552:                try {
553:                    BackupFacility.Handle id = BackupFacility.getDefault()
554:                            .backup(file);
555:                    if (backups == null) {
556:                        backups = new ArrayList<BackupFacility.Handle>();
557:                    }
558:                    backups.add(id);
559:                } catch (IOException ex) {
560:                    Exceptions.printStackTrace(ex);
561:                }
562:            }
563:
564:            private void undoFromBackups() {
565:                if (backups != null) {
566:                    try {
567:                        for (BackupFacility.Handle id : backups) {
568:                            id.restore();
569:                        }
570:                    } catch (IOException ex) {
571:                        Exceptions.printStackTrace(ex);
572:                    }
573:                    backups.clear();
574:                }
575:            }
576:
577:            // -----
578:
579:            private static class PreviewElement extends
580:                    SimpleRefactoringElementImplementation {
581:                private FileObject file;
582:
583:                PreviewElement(FileObject file) {
584:                    this .file = file;
585:                }
586:
587:                public String getText() {
588:                    return "GUI form update"; // NOI18N
589:                }
590:
591:                public String getDisplayText() {
592:                    return NbBundle.getMessage(FormRefactoringUpdate.class,
593:                            "CTL_RefactoringUpdate1"); // NOI18N
594:                }
595:
596:                public void performChange() {
597:                }
598:
599:                public Lookup getLookup() {
600:                    return Lookup.EMPTY;
601:                }
602:
603:                public FileObject getParentFile() {
604:                    return file;
605:                }
606:
607:                public PositionBounds getPosition() {
608:                    return null;
609:                }
610:            }
611:
612:            // -----
613:
614:            // RefactoringElementImplementation
615:            public String getText() {
616:                return "GUI form update";
617:            }
618:
619:            // RefactoringElementImplementation
620:            public String getDisplayText() {
621:                return NbBundle.getMessage(FormRefactoringUpdate.class,
622:                        "CTL_RefactoringUpdate2"); // NOI18N
623:            }
624:
625:            // RefactoringElementImplementation
626:            public Lookup getLookup() {
627:                return Lookup.EMPTY;
628:            }
629:
630:            // RefactoringElementImplementation
631:            public FileObject getParentFile() {
632:                return changingFile;
633:            }
634:
635:            // RefactoringElementImplementation
636:            public PositionBounds getPosition() {
637:                return null;
638:            }
639:
640:            // -----
641:
642:            /**
643:             * Elements and attributes that are used to search in when trying to replace
644:             * a non-FQN name (identifier) in custom code of a form.
645:             */
646:            private static final String[] FORM_ELEMENTS_ATTRS = {
647:                    "<Component ", " class=\"", // NOI18N
648:                    "<AuxValue name=\"JavaCodeGenerator_", " value=\"", // NOI18N
649:                    "<Property ", " preCode=\"", // NOI18N
650:                    "<Property ", " postCode=\"", // NOI18N
651:                    "<Connection ", " code=\"" // NOI18N
652:            };
653:
654:            /**
655:             * Replace the class or package name directly in the form file. It is
656:             * important not to cause other diff in the file.
657:             * ... A provisional strawman solution using textual replace, yuck ...
658:             * But should work fine with the *current* form file format and with
659:             * fully qualified class names, also covering the user's code (though
660:             * users will probably not use FQN.)
661:             * @return whether anything was changed in teh form file
662:             */
663:            private boolean replaceClassOrPkgName(String oldName,
664:                    String newName, boolean pkgName) {
665:                FileObject formFile = formDataObject.getFormFile();
666:                FileLock lock = null;
667:                OutputStream os = null;
668:                InputStream is = null;
669:                try {
670:                    lock = formFile.lock();
671:
672:                    String[] oldStr;
673:                    String[] newStr;
674:                    boolean shortName;
675:                    if (pkgName) {
676:                        oldName = oldName + "."; // NOI18N
677:                        newName = newName + "."; // NOI18N
678:                        oldStr = new String[] { oldName,
679:                                oldName.replace('.', '/') };
680:                        newStr = new String[] { newName,
681:                                newName.replace('.', '/') };
682:                        shortName = false;
683:                    } else {
684:                        shortName = !oldName.contains("."); // NOI18N
685:                        oldStr = new String[] { oldName };
686:                        newStr = new String[] { newName };
687:                    }
688:
689:                    String encoding = "UTF-8"; // NOI18N
690:                    String outString;
691:                    is = formFile.getInputStream();
692:                    BufferedReader reader = new BufferedReader(
693:                            new InputStreamReader(is, encoding));
694:                    if (!shortName) {
695:                        // With fully qualified name we can safely do plain textual
696:                        // search/replace over the file and get all changes covered
697:                        // (component class name elements, custom code, property editors,
698:                        // also icons and resource bundles if package name is changed, etc).
699:                        NameReplacer rep = new NameReplacer(oldStr, newStr,
700:                                (int) formFile.getSize());
701:                        String line = reader.readLine();
702:                        while (line != null) {
703:                            rep.append(line);
704:                            line = reader.readLine();
705:                            if (line != null) {
706:                                rep.append("\n"); // NOI18N
707:                            }
708:                        }
709:                        outString = rep.getResult(); // will also process the last char
710:                        if (!rep.anythingChanged()) {
711:                            return false;
712:                        }
713:                    } else {
714:                        // The replaced name is short with no '.', so it is too risky
715:                        // to do plain search/replace over the entire file content.
716:                        // Search only in the specific elements and attributes.
717:                        StringBuilder buf = new StringBuilder((int) formFile
718:                                .getSize());
719:                        boolean anyChange = false;
720:                        String line = reader.readLine();
721:                        while (line != null) {
722:                            String trimLine = line.trim();
723:                            for (int i = 0; i < FORM_ELEMENTS_ATTRS.length; i += 2) {
724:                                if (trimLine.startsWith(FORM_ELEMENTS_ATTRS[i])) {
725:                                    String attr = FORM_ELEMENTS_ATTRS[i + 1];
726:                                    int idx = line.indexOf(attr);
727:                                    if (idx > 0) {
728:                                        // get the value of the attribute - string enclosed in ""
729:                                        int idx1 = idx1 = idx + attr.length();
730:                                        if (!attr.endsWith("\"")) { // NOI18N
731:                                            while (idx1 < line.length()
732:                                                    && line.charAt(idx1) != '\"') { // NOI18N
733:                                                idx1++;
734:                                            }
735:                                            idx1++;
736:                                        }
737:                                        int idx2 = idx1;
738:                                        while (idx2 < line.length()
739:                                                && line.charAt(idx2) != '\"') { // NOI18N
740:                                            idx2++;
741:                                        }
742:                                        if (idx1 < line.length()
743:                                                && idx2 < line.length()) {
744:                                            String sub = line.substring(idx1,
745:                                                    idx2);
746:                                            if (sub.contains(oldName)) {
747:                                                NameReplacer rep = new NameReplacer(
748:                                                        oldStr, newStr, sub
749:                                                                .length());
750:                                                rep.append(sub);
751:                                                sub = rep.getResult(); // will also process the last char
752:                                                if (rep.anythingChanged()) {
753:                                                    line = line.substring(0,
754:                                                            idx1)
755:                                                            + sub
756:                                                            + line
757:                                                                    .substring(idx2);
758:                                                    anyChange = true;
759:                                                }
760:                                            }
761:                                        }
762:                                    }
763:                                }
764:                            }
765:                            buf.append(line);
766:                            line = reader.readLine();
767:                            if (line != null) {
768:                                buf.append("\n"); // NOI18N
769:                            }
770:                        }
771:                        if (!anyChange) {
772:                            return false;
773:                        }
774:                        outString = buf.toString();
775:                    }
776:
777:                    saveForUndo(formFile);
778:
779:                    is.close();
780:                    is = null;
781:
782:                    os = formFile.getOutputStream(lock);
783:                    os.write(outString.getBytes(encoding));
784:                } catch (Exception ex) {
785:                    Exceptions.printStackTrace(ex);
786:                    return false;
787:                } finally {
788:                    try {
789:                        if (is != null) {
790:                            is.close();
791:                        }
792:                        if (os != null) {
793:                            os.close();
794:                        }
795:                    } catch (IOException ex) { // ignore
796:                    }
797:                    if (lock != null) {
798:                        lock.releaseLock();
799:                    }
800:                }
801:                formFileRenameDone = true; // we don't need to do processCustomCode
802:                return true;
803:            }
804:
805:            private static class NameReplacer {
806:                private String[] toReplace;
807:                private String[] replaceWith;
808:                private int[] matchCounts;
809:
810:                private StringBuilder buffer;
811:                private StringBuilder pendingChars;
812:                private char lastChar;
813:
814:                private boolean anyChange;
815:                private boolean ended;
816:
817:                public NameReplacer(String[] toReplace, String[] replaceWith,
818:                        int len) {
819:                    this .toReplace = toReplace;
820:                    for (String s : toReplace) {
821:                        assert s != null && s.length() > 0;
822:                    }
823:                    for (String s : replaceWith) {
824:                        assert s != null && s.length() > 0;
825:                    }
826:                    this .replaceWith = replaceWith;
827:                    this .pendingChars = new StringBuilder(50);
828:                    this .buffer = new StringBuilder(len);
829:                    matchCounts = new int[toReplace.length];
830:                }
831:
832:                public void append(String str) {
833:                    assert !ended;
834:                    for (int i = 0; i < str.length(); i++) {
835:                        append(str.charAt(i));
836:                    }
837:                }
838:
839:                public String getResult() {
840:                    for (int i = 0; i < toReplace.length; i++) {
841:                        String template = toReplace[i];
842:                        int count = matchCounts[i];
843:                        if (count == template.length()) {
844:                            replace(i);
845:                            break;
846:                        }
847:                    }
848:                    writePendingChars();
849:                    ended = true;
850:                    return buffer.toString();
851:                }
852:
853:                /**
854:                 * Returns whether any replacement happened in written characters, i.e.
855:                 * whether the output differs from the input. Note this method should be
856:                 * called after all is written and getResult() called - to be sure the
857:                 * last character was processed properly.
858:                 * @return true if some chars were replaced in the text passed in via
859:                 *         append method
860:                 */
861:                public boolean anythingChanged() {
862:                    return anyChange;
863:                }
864:
865:                private void append(char c) {
866:                    int completeMatch = -1; // index of template string
867:                    boolean charMatch = false;
868:                    for (int i = 0; i < toReplace.length; i++) {
869:                        String template = toReplace[i];
870:                        int count = matchCounts[i];
871:                        if (count == template.length()) {
872:                            if (canEndHere(c)) { // so the name is not just a subset of a longer name
873:                                completeMatch = i;
874:                                break;
875:                            } else {
876:                                matchCounts[i] = 0;
877:                                continue;
878:                            }
879:                        }
880:                        if (template.charAt(count) == c) {
881:                            if (count > 0 || canStartHere()) { // not to start in the middle of a longer name
882:                                matchCounts[i] = count + 1;
883:                                charMatch = true;
884:                            }
885:                        } else {
886:                            matchCounts[i] = 0;
887:                        }
888:                    }
889:
890:                    if (completeMatch >= 0) {
891:                        replace(completeMatch);
892:                        buffer.append(c); // the first char after can't match (names can't follow without a gap)
893:                    } else if (charMatch) {
894:                        pendingChars.append(c);
895:                    } else {
896:                        writePendingChars();
897:                        buffer.append(c);
898:                    }
899:
900:                    lastChar = c;
901:                }
902:
903:                private boolean canStartHere() {
904:                    return lastChar != '.'
905:                            && lastChar != '/'
906:                            && (lastChar <= ' ' || !Character
907:                                    .isJavaIdentifierPart(lastChar));
908:                    // surprisingly 0 is considered as valid char
909:                }
910:
911:                private boolean canEndHere(char next) {
912:                    return lastChar == '.' || lastChar == '/'
913:                            || !Character.isJavaIdentifierPart(next);
914:                }
915:
916:                private void replace(int completeMatch) {
917:                    int preCount = pendingChars.length()
918:                            - matchCounts[completeMatch];
919:                    if (preCount > 0) {
920:                        buffer.append(pendingChars.substring(0, preCount));
921:                    }
922:                    buffer.append(replaceWith[completeMatch]);
923:                    for (int i = 0; i < matchCounts.length; i++) {
924:                        matchCounts[i] = 0;
925:                    }
926:                    pendingChars.delete(0, pendingChars.length());
927:                    anyChange = true;
928:                }
929:
930:                private void writePendingChars() {
931:                    if (pendingChars.length() > 0) {
932:                        buffer.append(pendingChars.toString());
933:                        pendingChars.delete(0, pendingChars.length());
934:                    }
935:                }
936:            }
937:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.