Source Code Cross Referenced for TokenHierarchyUpdate.java in  » IDE-Netbeans » lexer » org » netbeans » lib » lexer » 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 » lexer » org.netbeans.lib.lexer 
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:
042:        package org.netbeans.lib.lexer;
043:
044:        import java.util.ArrayList;
045:        import java.util.Collections;
046:        import java.util.HashMap;
047:        import java.util.List;
048:        import java.util.Map;
049:        import java.util.logging.Level;
050:        import java.util.logging.Logger;
051:        import org.netbeans.api.lexer.LanguagePath;
052:        import org.netbeans.api.lexer.TokenId;
053:        import org.netbeans.lib.lexer.inc.IncTokenList;
054:        import org.netbeans.lib.lexer.inc.MutableTokenList;
055:        import org.netbeans.lib.lexer.inc.TokenHierarchyEventInfo;
056:        import org.netbeans.lib.lexer.inc.TokenListChange;
057:        import org.netbeans.lib.lexer.inc.TokenListUpdater;
058:        import static org.netbeans.lib.lexer.LexerUtilsConstants.INVALID_STATE;
059:
060:        /**
061:         * Request for updating of token hierarchy after text modification
062:         * or custom embedding creation/removal.
063:         * <br/>
064:         * This class contains all the data and methods related to updating.
065:         *
066:         * @author Miloslav Metelka
067:         */
068:
069:        public final class TokenHierarchyUpdate {
070:
071:            // -J-Dorg.netbeans.lib.lexer.TokenHierarchyUpdate.level=FINE
072:            static final Logger LOG = Logger
073:                    .getLogger(TokenHierarchyUpdate.class.getName());
074:
075:            final TokenHierarchyEventInfo eventInfo;
076:
077:            private Map<LanguagePath, TLLInfo> path2info;
078:
079:            /**
080:             * Infos ordered from higher top levels of the hierarchy to lower levels.
081:             * Useful for top-down updating at the end.
082:             */
083:            private List<List<TLLInfo>> levelInfos;
084:
085:            TokenListChange<?> rootChange;
086:
087:            public TokenHierarchyUpdate(TokenHierarchyEventInfo eventInfo) {
088:                this .eventInfo = eventInfo;
089:            }
090:
091:            public void update(IncTokenList<?> incTokenList) {
092:                incTokenList.incrementModCount();
093:                // Update top-level token list first
094:                // It does not need any updateStatusImpl() since it's only for embedded token lists
095:                rootChange = updateTokenListByModification(incTokenList, null);
096:                eventInfo.setTokenChangeInfo(rootChange.tokenChangeInfo());
097:
098:                if (LOG.isLoggable(Level.FINE)) {
099:                    LOG.fine("ROOT CHANGE: " + rootChange.toString(0) + "\n"); // NOI18N
100:                }
101:
102:                // If there is an active lexer input operation (for not-yet finished
103:                // top-level token list lexing) refresh it because it would be damaged
104:                // by the performed token list update
105:                if (!incTokenList.isFullyLexed()) {
106:                    incTokenList.refreshLexerInputOperation();
107:                }
108:
109:                // Now the update goes to possibly embedded token list lists
110:                // based on the top-level change. If there are embeddings that join sections
111:                // this becomes a fairly complex thing.
112:                // 1. The updating must always go from upper levels to lower levels of the token hierarchy
113:                //    to ensure that the tokens of the possible joined embeddings get updated properly
114:                //    as the tokens created/removed at upper levels may contain embeddings that will
115:                //    need to be added/removed from token list lists on lower level.
116:                // 2. A single insert/remove may produce token updates at several
117:                //    places in the document. A top-level change of token with embedding
118:                //    will request the embedded token list update and that token list
119:                //    may be connected with another joined token list(s) with the same language path
120:                //    and the update may continue into these joined token lists.
121:
122:                // 3. The algorithm must collect both removed and added token lists
123:                //    in the TLLInfo.
124:                // 4. For a removed token list the updating must check nested embedded token lists
125:                //    because some embedded tokens of the removed embedded token list might contain
126:                //    another embedding that might also be maintained as token list list
127:                //    and need to be updated.
128:                // 5. The parent token list lists
129:                //    are always maintained too which simplifies the updating algorithm
130:                //    and speeds it up because the token list list marks whether it has any children
131:                //    or not and so the deep traversing only occurs if there are any children present.
132:                // 6. Additions may produce nested additions too so they need to be makred
133:                //    similarly to removals.
134:                if (rootChange.isBoundsChange()) {
135:                    processBoundsChangeEmbeddings(rootChange, null);
136:                } else {
137:                    // Mark changed area based on start of first mod.token and end of last mod.token
138:                    // of the root-level change
139:                    eventInfo.setMinAffectedStartOffset(rootChange.offset());
140:                    eventInfo.setMaxAffectedEndOffset(rootChange
141:                            .addedEndOffset());
142:                    processNonBoundsChange(rootChange);
143:                }
144:
145:                processLevelInfos();
146:            }
147:
148:            public void updateCreateEmbedding(
149:                    EmbeddedTokenList<?> addedTokenList) {
150:                TLLInfo info = info(addedTokenList.languagePath());
151:                if (info != NO_INFO) {
152:                    if (LOG.isLoggable(Level.FINE)) {
153:                        LOG.fine("THU.updateCreateEmbedding(): "
154:                                + addedTokenList.toStringHeader());
155:                    }
156:                    info.markAdded(addedTokenList);
157:                    processLevelInfos();
158:                }
159:            }
160:
161:            /**
162:             * update-status must be called by the caller.
163:             * @param removedTokenList token list removed by TS.removeEmbedding().
164:             */
165:            public void updateRemoveEmbedding(
166:                    EmbeddedTokenList<?> removedTokenList) {
167:                TLLInfo info = info(removedTokenList.languagePath());
168:                if (info != NO_INFO) {
169:                    if (LOG.isLoggable(Level.FINE)) {
170:                        LOG.fine("THU.updateRemoveEmbedding(): "
171:                                + removedTokenList.toStringHeader());
172:                    }
173:                    // update-status called by caller.
174:                    info.markRemoved(removedTokenList);
175:                    processLevelInfos();
176:                }
177:            }
178:
179:            void processBoundsChangeEmbeddings(TokenListChange<?> change,
180:                    TokenListChange<?> parentChange) {
181:                // Add an embedded change to the parent change (if exists)
182:                if (parentChange != null) {
183:                    parentChange.tokenChangeInfo().addEmbeddedChange(
184:                            change.tokenChangeInfo());
185:                }
186:                Object tokenOrEC = change.tokenChangeInfo().removedTokenList()
187:                        .tokenOrEmbeddingContainer(0);
188:                if (tokenOrEC.getClass() == EmbeddingContainer.class) {
189:                    TLLInfo info;
190:                    boolean hasChildren;
191:                    if (change.languagePath().size() > 1) {
192:                        info = info(change.languagePath());
193:                        hasChildren = (info != NO_INFO) ? info.tokenListList()
194:                                .hasChildren() : false;
195:                    } else { // root-level
196:                        info = NO_INFO;
197:                        hasChildren = (eventInfo.tokenHierarchyOperation()
198:                                .maxTokenListListPathSize() > 0);
199:                    }
200:                    EmbeddingContainer<?> ec = (EmbeddingContainer<?>) tokenOrEC;
201:                    rewrapECToken(ec, change); // Includes updateStatusImpl()
202:                    EmbeddedTokenList<?> etl = ec.firstEmbeddedTokenList();
203:                    if (etl != null
204:                            && etl != EmbeddedTokenList.NO_DEFAULT_EMBEDDING) {
205:                        // Check the text length beyond modification => end skip length must not be affected
206:                        int modRelOffset = eventInfo.modificationOffset()
207:                                - change.offset();
208:                        int beyondModLength = change.addedEndOffset()
209:                                - (eventInfo.modificationOffset() + eventInfo
210:                                        .diffLengthOrZero());
211:                        EmbeddedTokenList<?> prevEtl = null;
212:                        do {
213:                            TLLInfo childInfo = hasChildren ? info(etl
214:                                    .languagePath()) : NO_INFO;
215:                            // Check whether the change was not in the start or end skip lengths
216:                            // and if so then remove the embedding
217:                            if (modRelOffset >= etl.embedding()
218:                                    .startSkipLength()
219:                                    && beyondModLength >= etl.embedding()
220:                                            .endSkipLength()) { // Modification within embedding's bounds => embedding can stay
221:                                // Mark that the embedding should be updated
222:                                if (childInfo != NO_INFO) {
223:                                    // update-status called by rewrap-ec-token above
224:                                    childInfo.markBoundsChange(etl);
225:                                } else { // No child but want to update nested possible bounds changes
226:                                    if (etl.isInited()) {
227:                                        parentChange = change;
228:                                        // Perform change in child - it surely does not join the sections
229:                                        // since otherwise the childInfo could not be null
230:                                        // update-status done above for the embedding container
231:                                        change = updateTokenListByModification(
232:                                                etl, null);
233:                                        if (change.isBoundsChange()) {
234:                                            processBoundsChangeEmbeddings(
235:                                                    change, parentChange);
236:                                        } else {
237:                                            eventInfo
238:                                                    .setMinAffectedStartOffset(change
239:                                                            .offset());
240:                                            eventInfo
241:                                                    .setMaxAffectedEndOffset(change
242:                                                            .addedEndOffset());
243:                                        }
244:                                    }
245:                                }
246:                                prevEtl = etl;
247:                                etl = etl.nextEmbeddedTokenList();
248:
249:                            } else { // Mod in skip lengths => Remove the etl from chain
250:                                if (childInfo != NO_INFO) {
251:                                    // update-status already done as part of rewrap-token
252:                                    childInfo.markRemoved(etl);
253:                                }
254:                                // Remove embedding and get the next embedded token list (prevEtl stays the same)
255:                                etl = ec.removeEmbeddedTokenList(prevEtl, etl);
256:                            }
257:                        } while (etl != null
258:                                && etl != EmbeddedTokenList.NO_DEFAULT_EMBEDDING);
259:                    }
260:                }
261:            }
262:
263:            void processNonBoundsChange(TokenListChange<?> change) {
264:                TLLInfo info;
265:                boolean hasChildren;
266:                if (change.languagePath().size() >= 2) {
267:                    info = info(change.languagePath());
268:                    hasChildren = (info != NO_INFO && info.tokenListList()
269:                            .hasChildren());
270:                } else { // root change
271:                    info = NO_INFO;
272:                    hasChildren = (eventInfo.tokenHierarchyOperation()
273:                            .maxTokenListListPathSize() > 0);
274:                }
275:                if (hasChildren) {
276:                    // First mark the removed embeddings
277:                    TokenList<?> removedTokenList = change.tokenChangeInfo()
278:                            .removedTokenList();
279:                    if (removedTokenList != null) {
280:                        markRemovedEmbeddings(removedTokenList);
281:                    }
282:
283:                    // Now mark added embeddings
284:                    TokenList<?> currentTokenList = change.tokenChangeInfo()
285:                            .currentTokenList();
286:                    markAddedEmbeddings(currentTokenList, change.index(),
287:                            change.addedTokensOrBranchesCount());
288:                }
289:            }
290:
291:            /**
292:             * Collect removed embeddings for the given token list recursively
293:             * and nest deep enough for all maintained children
294:             * token list lists.
295:             */
296:            private void markRemovedEmbeddings(TokenList<?> removedTokenList) {
297:                int tokenCount = removedTokenList.tokenCountCurrent();
298:                for (int i = 0; i < tokenCount; i++) {
299:                    Object tokenOrEC = removedTokenList
300:                            .tokenOrEmbeddingContainer(i);
301:                    if (tokenOrEC.getClass() == EmbeddingContainer.class) {
302:                        EmbeddingContainer<?> ec = (EmbeddingContainer<?>) tokenOrEC;
303:                        ec.updateStatusImpl(); // Update status since markRemoved() will need it
304:                        EmbeddedTokenList<?> etl = ec.firstEmbeddedTokenList();
305:                        while (etl != null
306:                                && etl != EmbeddedTokenList.NO_DEFAULT_EMBEDDING) {
307:                            TLLInfo info = info(etl.languagePath());
308:                            if (info != NO_INFO) {
309:                                // update-status called above
310:                                info.markRemoved(etl);
311:                            }
312:                            etl = etl.nextEmbeddedTokenList();
313:                        }
314:                    }
315:                }
316:            }
317:
318:            private void markAddedEmbeddings(TokenList<?> tokenList, int index,
319:                    int addedCount) {
320:                for (int i = 0; i < addedCount; i++) {
321:                    // Ensure that the default embedding gets possibly created
322:                    EmbeddedTokenList<?> etl = EmbeddingContainer
323:                            .embeddedTokenList(tokenList, index + i, null);
324:                    if (etl != null) {
325:                        TLLInfo info = info(etl.languagePath());
326:                        if (info != NO_INFO) {
327:                            // Mark that there was a new embedded token list added
328:                            // There should be no updateStatusImpl() necessary since the token lists are new
329:                            // and the parent embedding container was surely updated by the updating process.
330:                            info.markAdded(etl);
331:                        }
332:                    }
333:                }
334:            }
335:
336:            private void processLevelInfos() {
337:                // Now relex the changes in affected token list lists
338:                // i.e. fix the tokens after the token lists removals/additions.
339:                // The higher-level updates
340:                if (levelInfos != null) {
341:                    // The list can be extended by additional items dynamically during iteration
342:                    for (int i = 0; i < levelInfos.size(); i++) {
343:                        List<TLLInfo> infos = levelInfos.get(i);
344:                        // The "infos" list should not be extended by additional items dynamically during iteration
345:                        // However an extra items can be added at the deeper levels.
346:                        for (int j = 0; j < infos.size(); j++) {
347:                            infos.get(j).update();
348:                        }
349:                    }
350:                }
351:
352:                // Assert that update was called on all infos
353:                if (LOG.isLoggable(Level.FINER) && levelInfos != null) {
354:                    for (List<TLLInfo> infos : levelInfos) {
355:                        for (TLLInfo info : infos) {
356:                            if (!info.updateCalled) {
357:                                throw new IllegalStateException(
358:                                        "Update not called on tokenListList\n" + // NOI18N
359:                                                info.tokenListList);
360:                            }
361:                        }
362:                    }
363:                }
364:            }
365:
366:            <T extends TokenId> TokenListChange<T> updateTokenListByModification(
367:                    MutableTokenList<T> tokenList, Object zeroIndexRelexState) {
368:                TokenListChange<T> change = new TokenListChange<T>(tokenList);
369:                //        if (tokenList instanceof EmbeddedTokenList) {
370:                //            ((EmbeddedTokenList)tokenList).embeddingContainer().checkStatusUpdated();
371:                //        }
372:                TokenListUpdater.update(tokenList, eventInfo
373:                        .modificationOffset(), eventInfo.insertedLength(),
374:                        eventInfo.removedLength(), change, zeroIndexRelexState);
375:                return change;
376:            }
377:
378:            /**
379:             * Return tll info or NO_INFO if the token list list is not maintained
380:             * for the given language path.
381:             */
382:            private TLLInfo info(LanguagePath languagePath) {
383:                if (path2info == null) { // Init since it will contain NO_INFO
384:                    path2info = new HashMap<LanguagePath, TLLInfo>(4, 0.5f);
385:                }
386:                TLLInfo info = path2info.get(languagePath);
387:                if (info == null) {
388:                    TokenListList tll = eventInfo.tokenHierarchyOperation()
389:                            .existingTokenListList(languagePath);
390:                    if (tll != null) {
391:                        info = new TLLInfo(this , tll);
392:                        int index = languagePath.size() - 2;
393:                        if (levelInfos == null) {
394:                            levelInfos = new ArrayList<List<TLLInfo>>(index + 1);
395:                        }
396:                        while (levelInfos.size() <= index) {
397:                            levelInfos.add(new ArrayList<TLLInfo>(2));
398:                        }
399:                        levelInfos.get(index).add(info);
400:                    } else { // No token list list for the given language path
401:                        info = NO_INFO;
402:                    }
403:                    path2info.put(languagePath, info);
404:                }
405:                return info;
406:            }
407:
408:            private <T extends TokenId> void rewrapECToken(
409:                    EmbeddingContainer<T> ec, TokenListChange<?> change) {
410:                @SuppressWarnings("unchecked")
411:                TokenListChange<T> tChange = (TokenListChange<T>) change;
412:                ec.reinit(tChange.addedToken(0));
413:                ec.updateStatusImpl();
414:                tChange.tokenList().wrapToken(tChange.index(), ec);
415:            }
416:
417:            /**
418:             * Special constant value to avoid double map search for token list lists updating.
419:             */
420:            static final TLLInfo NO_INFO = new TLLInfo(null, null);
421:
422:            /**
423:             * Information about update in a single token list list.
424:             */
425:            static final class TLLInfo {
426:
427:                final TokenHierarchyUpdate update;
428:
429:                final TokenListList tokenListList;
430:
431:                int index;
432:
433:                int removeCount;
434:
435:                List<TokenList<?>> added;
436:
437:                TokenListChange<?> change;
438:
439:                boolean updateCalled;
440:
441:                public TLLInfo(TokenHierarchyUpdate update,
442:                        TokenListList tokenListList) {
443:                    this .update = update;
444:                    this .tokenListList = tokenListList;
445:                    this .index = -1;
446:                    this .added = Collections.emptyList();
447:                }
448:
449:                public TokenListList tokenListList() {
450:                    return tokenListList;
451:                }
452:
453:                /**
454:                 * Mark the given token list as removed in this token list list.
455:                 * All removed token lists should be marked by their increasing offset
456:                 * so it should be necessary to search for the index just once.
457:                 * <br/>
458:                 * It's expected that updateStatusImpl() was already called
459:                 * on the corresponding embedding container.
460:                 */
461:                public void markRemoved(EmbeddedTokenList<?> removedTokenList) {
462:                    boolean indexWasMinusOne; // Used for possible exception cause debugging
463:                    //            removedTokenList.embeddingContainer().checkStatusUpdated();
464:                    if (index == -1) {
465:                        checkUpdateNotCalledYet();
466:                        indexWasMinusOne = true;
467:                        index = tokenListList.findIndexDuringUpdate(
468:                                removedTokenList, update.eventInfo
469:                                        .modificationOffset(), update.eventInfo
470:                                        .removedLength());
471:                        assert (index >= 0) : "index=" + index + " < 0"; // NOI18N
472:                    } else { // Index already initialized
473:                        indexWasMinusOne = false;
474:                    }
475:                    TokenList<?> markedForRemoveTokenList = tokenListList
476:                            .getOrNull(index + removeCount);
477:                    if (markedForRemoveTokenList != removedTokenList) {
478:                        int realIndex = tokenListList.indexOf(removedTokenList);
479:                        throw new IllegalStateException("Removing at index="
480:                                + index
481:                                + // NOI18N
482:                                " but real index is "
483:                                + realIndex
484:                                + // NOI18N
485:                                " (indexWasMinusOne="
486:                                + indexWasMinusOne
487:                                + ").\n"
488:                                + // NOI18N
489:                                "Wishing to remove tokenList\n"
490:                                + removedTokenList
491:                                + // NOI18N
492:                                "\nbut marked-for-remove tokenList is \n"
493:                                + markedForRemoveTokenList
494:                                + // NOI18N
495:                                "\nfrom tokenListList\n" + tokenListList
496:                                + // NOI18N
497:                                "\n\nModification description:\n"
498:                                + update.eventInfo
499:                                        .modificationDescription(true) // NOI18N
500:                        );
501:                    }
502:                    removeCount++;
503:                }
504:
505:                /**
506:                 * Mark the given token list to be added to this list of token lists.
507:                 * At the end first the token lists marked for removal will be removed
508:                 * and then the token lists marked for addition will be added.
509:                 * <br/>
510:                 * It's expected that updateStatusImpl() was already called
511:                 * on the corresponding embedding container.
512:                 */
513:                public void markAdded(EmbeddedTokenList<?> addedTokenList) {
514:                    //            addedTokenList.embeddingContainer().checkStatusUpdated();
515:                    if (added.size() == 0) {
516:                        checkUpdateNotCalledYet();
517:                        if (index == -1) {
518:                            index = tokenListList.findIndex(addedTokenList
519:                                    .startOffset());
520:                            assert (index >= 0) : "index=" + index + " < 0"; // NOI18N
521:                        }
522:                        added = new ArrayList<TokenList<?>>(4);
523:                    }
524:                    added.add(addedTokenList);
525:                }
526:
527:                /**
528:                 * Mark that a parent's token list's bounds change need to be propagated
529:                 * into the given (child) token list.
530:                 * <br/>
531:                 * It's expected that updateStatusImpl() was already called
532:                 * on the corresponding embedding container.
533:                 */
534:                public void markBoundsChange(EmbeddedTokenList<?> etl) {
535:                    assert (index == -1) : "index=" + index + " != -1"; // Should be the first one
536:                    //            etl.embeddingContainer().checkStatusUpdated();
537:                    checkUpdateNotCalledYet();
538:                    index = tokenListList.findIndex(etl.startOffset());
539:                }
540:
541:                public void update() {
542:                    checkUpdateNotCalledYet();
543:                    updateCalled = true;
544:                    // Update this level (and language path).
545:                    // All the removed and added sections resulting from parent change(s)
546:                    // are already marked.
547:                    if (index == -1)
548:                        return; // Nothing to do
549:
550:                    if (removeCount == 0 && added.size() == 0) { // Bounds change only
551:                        if (LOG.isLoggable(Level.FINE)) {
552:                            LOG.fine("TLLInfo.update(): BOUNDS-CHANGE: "
553:                                    + tokenListList.languagePath().mimePath() + // NOI18N
554:                                    " index=" + index + // NOI18N
555:                                    '\n');
556:                        }
557:
558:                        EmbeddedTokenList<?> etl = tokenListList.get(index);
559:                        etl.embeddingContainer().updateStatusImpl();
560:                        Object matchState = LexerUtilsConstants.endState(etl);
561:                        Object relexState = tokenListList.relexState(index);
562:                        // update-status called above
563:                        TokenListChange<?> chng = update
564:                                .updateTokenListByModification(etl, relexState);
565:                        relexState = LexerUtilsConstants.endState(etl,
566:                                relexState);
567:                        // Prevent bounds change in case the states at the end of the section would not match
568:                        // which leads to relexing of the next section.
569:                        if (chng.isBoundsChange()
570:                                && LexerUtilsConstants.statesEqual(relexState,
571:                                        matchState)) {
572:                            TokenListChange<?> parentChange = (tokenListList
573:                                    .languagePath().size() == 2) ? update.rootChange
574:                                    : update.info(tokenListList.languagePath()
575:                                            .parent()).change;
576:                            update.processBoundsChangeEmbeddings(chng,
577:                                    parentChange);
578:                        } else { // Regular change
579:                            update.processNonBoundsChange(chng);
580:                        }
581:                        relexAfterLastModifiedSection(index + 1, relexState,
582:                                matchState);
583:
584:                    } else { // Non-bounds change
585:                        if (LOG.isLoggable(Level.FINE)) {
586:                            LOG.fine("TLLInfo.update(): REPLACE: "
587:                                    + tokenListList.languagePath().mimePath() + // NOI18N
588:                                    " index=" + index + // NOI18N
589:                                    ", removeCount=" + removeCount + // NOI18N
590:                                    ", added.size()=" + added.size() + // NOI18N
591:                                    '\n');
592:                        }
593:
594:                        TokenList<?>[] removed = tokenListList.replace(index,
595:                                removeCount, added);
596:                        // Mark embeddings of removed token lists as removed
597:                        if (tokenListList.hasChildren()) {
598:                            for (int i = 0; i < removed.length; i++) {
599:                                TokenList<?> removedTokenList = removed[i];
600:                                update.markRemovedEmbeddings(removedTokenList);
601:                            }
602:                        }
603:
604:                        Object relexState; // State from which the relexing will start
605:                        Object matchState = INVALID_STATE; // State that needs to be reached by relexing
606:                        if (tokenListList.joinSections()) { // Need to find the right relexState
607:                            // Must update the token list by incremental algorithm
608:                            // Find non-empty token list and take last token's state
609:                            relexState = tokenListList.relexState(index);
610:                            for (int i = removed.length - 1; i >= 0
611:                                    && matchState == INVALID_STATE; i--) {
612:                                matchState = LexerUtilsConstants
613:                                        .endState((EmbeddedTokenList<?>) removed[i]);
614:                            }
615:                            // Find the start state as the previous non-empty section's last token's state
616:                            // for case there would be no token lists added or all the added sections
617:                            // would be empty.
618:                            if (matchState == INVALID_STATE) // None or just empty sections were removed
619:                                matchState = relexState;
620:
621:                        } else { // Not joining the sections
622:                            relexState = null;
623:                        }
624:
625:                        // Relex all the added token lists (just by asking for tokenCount - init() will be done)
626:                        for (int i = 0; i < added.size(); i++) {
627:                            EmbeddedTokenList<?> tokenList = (EmbeddedTokenList<?>) added
628:                                    .get(i);
629:                            assert (!tokenList.isInited());
630:                            tokenList.init(relexState);
631:                            if (tokenList.embedding().joinSections()) {
632:                                tokenListList.setJoinSections(true);
633:                            }
634:                            relexState = LexerUtilsConstants.endState(
635:                                    (EmbeddedTokenList<?>) tokenList,
636:                                    relexState);
637:                            if (tokenListList.hasChildren()) {
638:                                update.markAddedEmbeddings(tokenList, 0,
639:                                        tokenList.tokenCount());
640:                            }
641:                            // Added token lists should not require updateStatus()
642:                            update.eventInfo.setMaxAffectedEndOffset(tokenList
643:                                    .endOffset());
644:                        }
645:
646:                        if (tokenListList.joinSections()) {
647:                            index += added.size();
648:                            relexAfterLastModifiedSection(index, relexState,
649:                                    matchState);
650:                        }
651:                    }
652:
653:                    //            for (EmbeddedTokenList<?> etl : tokenListList) {
654:                    //                etl.embeddingContainer().updateStatusImpl();
655:                    //                if (etl.embeddingContainer().isRemoved())
656:                    //                    throw new IllegalStateException();
657:                    //            }
658:                    // Set index to -1 to simplify correctness checking
659:                    index = -1;
660:                }
661:
662:                void checkUpdateNotCalledYet() {
663:                    if (updateCalled) {
664:                        throw new IllegalStateException(
665:                                "Update already called on \n" + tokenListList);
666:                    }
667:                }
668:
669:                private void relexAfterLastModifiedSection(int index,
670:                        Object relexState, Object matchState) {
671:                    // Must continue relexing existing section(s) (from a different start state)
672:                    // until the relexing will stop before the last token of the given section.
673:                    EmbeddedTokenList<?> etl;
674:                    while (!LexerUtilsConstants.statesEqual(relexState,
675:                            matchState)
676:                            && (etl = tokenListList.getOrNull(index)) != null) {
677:                        etl.embeddingContainer().updateStatusImpl();
678:                        if (etl.tokenCount() > 0) {
679:                            // Remember state after the last token of the given section
680:                            matchState = etl.state(etl.tokenCount() - 1);
681:                            // updateStatusImpl() just called
682:                            TokenListChange<?> chng = updateTokenListAtStart(
683:                                    etl, etl.startOffset(), relexState);
684:                            update.processNonBoundsChange(chng);
685:                            // Since the section is non-empty (checked above) there should be >0 tokens
686:                            relexState = etl.state(etl.tokenCount() - 1);
687:                        }
688:                        index++;
689:                    }
690:                }
691:
692:                private <T extends TokenId> TokenListChange<T> updateTokenListAtStart(
693:                        EmbeddedTokenList<T> etl, int offset,
694:                        Object zeroIndexRelexState) {
695:                    TokenListChange<T> chng = new TokenListChange<T>(etl);
696:                    //            etl.embeddingContainer().checkStatusUpdated();
697:                    TokenListUpdater.update(etl, offset, 0, 0, chng,
698:                            zeroIndexRelexState);
699:                    update.eventInfo.setMaxAffectedEndOffset(chng
700:                            .addedEndOffset());
701:                    return chng;
702:                }
703:
704:            }
705:
706:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.