Source Code Cross Referenced for Evolver.java in  » JMX » je » com » sleepycat » persist » impl » 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 » JMX » je » com.sleepycat.persist.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: Evolver.java,v 1.7.2.5 2008/01/07 15:14:19 cwl Exp $
007:         */
008:
009:        package com.sleepycat.persist.impl;
010:
011:        import java.util.ArrayList;
012:        import java.util.List;
013:        import java.util.HashMap;
014:        import java.util.HashSet;
015:        import java.util.IdentityHashMap;
016:        import java.util.Map;
017:        import java.util.Set;
018:
019:        import com.sleepycat.je.DatabaseException;
020:        import com.sleepycat.je.DatabaseNotFoundException;
021:        import com.sleepycat.je.Environment;
022:        import com.sleepycat.je.Transaction;
023:        import com.sleepycat.persist.evolve.Converter;
024:        import com.sleepycat.persist.evolve.Deleter;
025:        import com.sleepycat.persist.evolve.Mutation;
026:        import com.sleepycat.persist.evolve.Mutations;
027:        import com.sleepycat.persist.evolve.Renamer;
028:        import com.sleepycat.persist.model.SecondaryKeyMetadata;
029:
030:        /**
031:         * Evolves each old format that is still relevant if necessary, using Mutations
032:         * to configure deleters, renamers, and converters.
033:         *
034:         * @author Mark Hayes
035:         */
036:        class Evolver {
037:
038:            static final int EVOLVE_NONE = 0;
039:            static final int EVOLVE_NEEDED = 1;
040:            static final int EVOLVE_FAILURE = 2;
041:
042:            private PersistCatalog catalog;
043:            private String storePrefix;
044:            private Mutations mutations;
045:            private Map<String, Format> newFormats;
046:            private boolean forceEvolution;
047:            private boolean disallowClassChanges;
048:            private boolean nestedFormatsChanged;
049:            private Map<Format, Format> changedFormats;
050:            private StringBuilder errors;
051:            private Set<String> deleteDbs;
052:            private Map<String, String> renameDbs;
053:            private Map<Format, Format> renameFormats;
054:            private Map<Integer, Boolean> evolvedFormats;
055:            private List<Format> unprocessedFormats;
056:            private Map<Format, Set<Format>> subclassMap;
057:
058:            Evolver(PersistCatalog catalog, String storePrefix,
059:                    Mutations mutations, Map<String, Format> newFormats,
060:                    boolean forceEvolution, boolean disallowClassChanges) {
061:                this .catalog = catalog;
062:                this .storePrefix = storePrefix;
063:                this .mutations = mutations;
064:                this .newFormats = newFormats;
065:                this .forceEvolution = forceEvolution;
066:                this .disallowClassChanges = disallowClassChanges;
067:                changedFormats = new IdentityHashMap<Format, Format>();
068:                errors = new StringBuilder();
069:                deleteDbs = new HashSet<String>();
070:                renameDbs = new HashMap<String, String>();
071:                renameFormats = new IdentityHashMap<Format, Format>();
072:                evolvedFormats = new HashMap<Integer, Boolean>();
073:                unprocessedFormats = new ArrayList<Format>();
074:                subclassMap = catalog.getSubclassMap();
075:            }
076:
077:            final Mutations getMutations() {
078:                return mutations;
079:            }
080:
081:            /**
082:             * Returns whether any formats were changed during evolution, and therefore
083:             * need to be stored in the catalog.
084:             */
085:            boolean areFormatsChanged() {
086:                return !changedFormats.isEmpty();
087:            }
088:
089:            /**
090:             * Returns whether the given format was changed during evolution.
091:             */
092:            boolean isFormatChanged(Format format) {
093:                return changedFormats.containsKey(format);
094:            }
095:
096:            private void setFormatsChanged(Format oldFormat) {
097:                checkClassChangesAllowed(oldFormat);
098:                changedFormats.put(oldFormat, oldFormat);
099:                nestedFormatsChanged = true;
100:                /* PersistCatalog.expectNoClassChanges is true in unit tests only. */
101:                if (PersistCatalog.expectNoClassChanges) {
102:                    throw new IllegalStateException("expectNoClassChanges");
103:                }
104:            }
105:
106:            private void checkClassChangesAllowed(Format oldFormat) {
107:                if (disallowClassChanges) {
108:                    throw new IllegalStateException(
109:                            "When performing an upgrade changes are not allowed "
110:                                    + "but were made to: "
111:                                    + oldFormat.getClassName());
112:                }
113:            }
114:
115:            /**
116:             * Returns the set of formats for a specific superclass format, or null if
117:             * the superclass is not a complex type or has not subclasses.
118:             */
119:            Set<Format> getSubclassFormats(Format super Format) {
120:                return subclassMap.get(super Format);
121:            }
122:
123:            /**
124:             * Returns an error string if any mutations are invalid or missing, or
125:             * returns null otherwise.  If non-null is returned, the store may not be
126:             * opened.
127:             */
128:            String getErrors() {
129:                if (errors.length() > 0) {
130:                    return errors.toString();
131:                } else {
132:                    return null;
133:                }
134:            }
135:
136:            /**
137:             * Adds a newline and the given error.
138:             */
139:            private void addError(String error) {
140:                if (errors.length() > 0) {
141:                    errors.append("\n---\n");
142:                }
143:                errors.append(error);
144:            }
145:
146:            private String getClassVersionLabel(Format format, String prefix) {
147:                if (format != null) {
148:                    return prefix + " class: " + format.getClassName()
149:                            + " version: " + format.getVersion();
150:                } else {
151:                    return "";
152:                }
153:            }
154:
155:            /**
156:             * Adds a specified error when no specific mutation is involved.
157:             */
158:            void addEvolveError(Format oldFormat, Format newFormat,
159:                    String scenario, String error) {
160:                checkClassChangesAllowed(oldFormat);
161:                if (scenario == null) {
162:                    scenario = "Error";
163:                }
164:                addError(scenario + " when evolving"
165:                        + getClassVersionLabel(oldFormat, "")
166:                        + getClassVersionLabel(newFormat, " to") + " Error: "
167:                        + error);
168:            }
169:
170:            /**
171:             * Adds an error for an invalid mutation.
172:             */
173:            void addInvalidMutation(Format oldFormat, Format newFormat,
174:                    Mutation mutation, String error) {
175:                checkClassChangesAllowed(oldFormat);
176:                addError("Invalid mutation: " + mutation
177:                        + getClassVersionLabel(oldFormat, " For")
178:                        + getClassVersionLabel(newFormat, " New") + " Error: "
179:                        + error);
180:            }
181:
182:            /**
183:             * Adds an error for a missing mutation.
184:             */
185:            void addMissingMutation(Format oldFormat, Format newFormat,
186:                    String error) {
187:                checkClassChangesAllowed(oldFormat);
188:                addError("Mutation is missing to evolve"
189:                        + getClassVersionLabel(oldFormat, "")
190:                        + getClassVersionLabel(newFormat, " to") + " Error: "
191:                        + error);
192:            }
193:
194:            /**
195:             * Called by PersistCatalog for all non-entity formats.
196:             */
197:            void addNonEntityFormat(Format oldFormat) {
198:                unprocessedFormats.add(oldFormat);
199:            }
200:
201:            /**
202:             * Called by PersistCatalog after calling evolveFormat or
203:             * addNonEntityFormat for all old formats.
204:             *
205:             * We do not require deletion of an unreferenced class for three
206:             * reasons: 1) built-in proxy classes may not be referenced, 2) the
207:             * user may wish to declare persistent classes that are not yet used.
208:             */
209:            void finishEvolution() {
210:                /* Process unreferenced classes. */
211:                for (Format oldFormat : unprocessedFormats) {
212:                    oldFormat.setUnused(true);
213:                    Integer oldFormatId = oldFormat.getId();
214:                    if (!evolvedFormats.containsKey(oldFormatId)) {
215:                        evolvedFormats.put(oldFormatId, true);
216:                        boolean result = evolveFormatInternal(oldFormat);
217:                        evolvedFormats.put(oldFormatId, result);
218:                    }
219:                }
220:            }
221:
222:            /**
223:             * Called by PersistCatalog for all entity formats, and by Format.evolve
224:             * methods for all potentially referenced non-entity formats.
225:             */
226:            boolean evolveFormat(Format oldFormat) {
227:                boolean result;
228:                boolean trackEntityChanges = oldFormat.getLatestVersion()
229:                        .getEntityFormat() != null;
230:                boolean saveNestedFormatsChanged = nestedFormatsChanged;
231:                if (trackEntityChanges) {
232:                    nestedFormatsChanged = false;
233:                }
234:                Integer oldFormatId = oldFormat.getId();
235:                if (evolvedFormats.containsKey(oldFormatId)) {
236:                    result = evolvedFormats.get(oldFormatId);
237:                } else {
238:                    evolvedFormats.put(oldFormatId, true);
239:                    result = evolveFormatInternal(oldFormat);
240:                    evolvedFormats.put(oldFormatId, result);
241:                }
242:                if (oldFormat.getLatestVersion().isNew()) {
243:                    nestedFormatsChanged = true;
244:                }
245:                if (trackEntityChanges) {
246:                    if (nestedFormatsChanged) {
247:                        Format latest = oldFormat.getLatestVersion()
248:                                .getEntityFormat();
249:                        if (latest != null) {
250:                            latest.setEvolveNeeded(true);
251:                        }
252:                    }
253:                    nestedFormatsChanged = saveNestedFormatsChanged;
254:                }
255:                return result;
256:            }
257:
258:            /**
259:             * Tries to evolve a given existing format to the current version of the
260:             * class and returns false if an invalid mutation is encountered or the
261:             * configured mutations are not sufficient.
262:             */
263:            private boolean evolveFormatInternal(Format oldFormat) {
264:
265:                /* Predefined formats and deleted classes never need evolving. */
266:                if (Format.isPredefined(oldFormat) || oldFormat.isDeleted()) {
267:                    return true;
268:                }
269:
270:                /* Get class mutations. */
271:                String oldName = oldFormat.getClassName();
272:                int oldVersion = oldFormat.getVersion();
273:                Renamer renamer = mutations.getRenamer(oldName, oldVersion,
274:                        null);
275:                Deleter deleter = mutations.getDeleter(oldName, oldVersion,
276:                        null);
277:                Converter converter = mutations.getConverter(oldName,
278:                        oldVersion, null);
279:                if (deleter != null && (converter != null || renamer != null)) {
280:                    addInvalidMutation(oldFormat, null, deleter,
281:                            "Class Deleter not allowed along with a Renamer or "
282:                                    + "Converter for the same class");
283:                    return false;
284:                }
285:
286:                /*
287:                 * For determining the new name, arrays get special treatment.  The
288:                 * component format is evolved in the process, and we disallow muations
289:                 * for arrays.
290:                 */
291:                String newName;
292:                if (oldFormat.isArray()) {
293:                    if (deleter != null || converter != null || renamer != null) {
294:                        Mutation mutation = (deleter != null) ? deleter
295:                                : ((converter != null) ? converter : renamer);
296:                        addInvalidMutation(oldFormat, null, mutation,
297:                                "Mutations not allowed for an array");
298:                        return false;
299:                    }
300:                    Format compFormat = oldFormat.getComponentType();
301:                    if (!evolveFormat(compFormat)) {
302:                        return false;
303:                    }
304:                    Format latest = compFormat.getLatestVersion();
305:                    if (latest != compFormat) {
306:                        newName = (latest.isArray() ? "[" : "[L")
307:                                + latest.getClassName() + ';';
308:                    } else {
309:                        newName = oldName;
310:                    }
311:                } else {
312:                    newName = (renamer != null) ? renamer.getNewName()
313:                            : oldName;
314:                }
315:
316:                /* Try to get the new class format.  Save exception for later. */
317:                Format newFormat;
318:                String newFormatException;
319:                try {
320:                    Class newClass = SimpleCatalog.classForName(newName);
321:                    try {
322:                        newFormat = catalog.createFormat(newClass, newFormats);
323:                        assert newFormat != oldFormat : newFormat
324:                                .getClassName();
325:                        newFormatException = null;
326:                    } catch (Exception e) {
327:                        newFormat = null;
328:                        newFormatException = e.toString();
329:                    }
330:                } catch (ClassNotFoundException e) {
331:                    newFormat = null;
332:                    newFormatException = e.toString();
333:                }
334:
335:                if (newFormat != null) {
336:
337:                    /*
338:                     * If the old format is not the existing latest version and the new
339:                     * format is not an existing format, then we must evolve the latest
340:                     * old version to the new format first.  We cannot evolve old
341:                     * format to a new format that may be discarded because it is equal
342:                     * to the latest existing format (which will remain the current
343:                     * version).
344:                     */
345:                    if (oldFormat != oldFormat.getLatestVersion()
346:                            && newFormat.getPreviousVersion() == null) {
347:                        assert newFormats.containsValue(newFormat);
348:                        Format oldLatestFormat = oldFormat.getLatestVersion();
349:                        evolveFormat(oldLatestFormat);
350:                        if (oldLatestFormat == oldLatestFormat
351:                                .getLatestVersion()) {
352:                            assert !newFormats.containsValue(newFormat);
353:                            /* newFormat equals oldLatestFormat and was discarded. */
354:                            newFormat = oldLatestFormat;
355:                        }
356:                    }
357:
358:                    /*
359:                     * If the old format was previously evolved to the new format
360:                     * (which means the new format is actually an existing format),
361:                     * then there is nothing to do.  This is the case where no class
362:                     * changes were made.
363:                     *
364:                     * However, if mutations were specified when opening the catalog
365:                     * that are different than the mutations last used, then we must
366:                     * force the re-evolution of all old formats.
367:                     */
368:                    if (!forceEvolution
369:                            && newFormat == oldFormat.getLatestVersion()) {
370:                        return true;
371:                    }
372:                }
373:
374:                /* Apply class Renamer and continue if successful. */
375:                if (renamer != null) {
376:                    if (!applyRenamer(renamer, oldFormat, newFormat)) {
377:                        return false;
378:                    }
379:                }
380:
381:                /* Apply class Converter and return. */
382:                if (converter != null) {
383:                    if (oldFormat.isEntity()) {
384:                        if (newFormat == null || !newFormat.isEntity()) {
385:                            addInvalidMutation(
386:                                    oldFormat,
387:                                    newFormat,
388:                                    deleter,
389:                                    "Class converter not allowed for an entity class "
390:                                            + "that is no longer present or not having an "
391:                                            + "@Entity annotation");
392:                            return false;
393:                        }
394:                        if (!oldFormat.evolveMetadata(newFormat, converter,
395:                                this )) {
396:                            return false;
397:                        }
398:                    }
399:                    return applyConverter(converter, oldFormat, newFormat);
400:                }
401:
402:                /* Apply class Deleter and return. */
403:                boolean needDeleter = (newFormat == null)
404:                        || (newFormat.isEntity() != oldFormat.isEntity());
405:                if (deleter != null) {
406:                    if (!needDeleter) {
407:                        addInvalidMutation(
408:                                oldFormat,
409:                                newFormat,
410:                                deleter,
411:                                "Class deleter not allowed when the class and its "
412:                                        + "@Entity or @Persistent annotation is still present");
413:                        return false;
414:                    }
415:                    return applyDeleter(deleter, oldFormat, newFormat);
416:                } else {
417:                    if (needDeleter) {
418:                        if (newFormat == null) {
419:                            assert newFormatException != null;
420:                            /* FindBugs newFormat known to be null excluded. */
421:                            addMissingMutation(oldFormat, newFormat,
422:                                    newFormatException);
423:                        } else {
424:                            addMissingMutation(oldFormat, newFormat,
425:                                    "@Entity switched to/from @Persistent");
426:                        }
427:                        return false;
428:                    }
429:                }
430:
431:                /*
432:                 * Class-level mutations have been applied.  Now apply field mutations
433:                 * (for complex classes) or special conversions (enum conversions, for
434:                 * example) by calling the old format's evolve method.
435:                 */
436:                return oldFormat.evolve(newFormat, this );
437:            }
438:
439:            /**
440:             * Use the old format and discard the new format.  Called by
441:             * Format.evolve when the old and new formats are identical.
442:             */
443:            void useOldFormat(Format oldFormat, Format newFormat) {
444:                Format renamedFormat = renameFormats.get(oldFormat);
445:                if (renamedFormat != null) {
446:
447:                    /*
448:                     * The format was renamed but, because this method is called, we
449:                     * know that no other class changes were made.  Use the new/renamed
450:                     * format as the reader.
451:                     */
452:                    assert renamedFormat == newFormat;
453:                    useEvolvedFormat(oldFormat, renamedFormat, renamedFormat);
454:                } else if (newFormat != null
455:                        && oldFormat.getVersion() != newFormat.getVersion()) {
456:                    /* The user wants a new version number, but no other changes. */
457:                    useEvolvedFormat(oldFormat, newFormat, newFormat);
458:                } else {
459:                    /* The new format is discarded. */
460:                    catalog.useExistingFormat(oldFormat);
461:                    if (newFormat != null) {
462:                        newFormats.remove(newFormat.getClassName());
463:                    }
464:                }
465:            }
466:
467:            /**
468:             * Install an evolver Reader in the old format.  Called by Format.evolve
469:             * when the old and new formats are not identical.
470:             */
471:            void useEvolvedFormat(Format oldFormat, Reader evolveReader,
472:                    Format newFormat) {
473:                oldFormat.setReader(evolveReader);
474:                if (newFormat != null) {
475:                    oldFormat.setLatestVersion(newFormat);
476:                }
477:                setFormatsChanged(oldFormat);
478:            }
479:
480:            private boolean applyRenamer(Renamer renamer, Format oldFormat,
481:                    Format newFormat) {
482:                if (!checkUpdatedVersion(renamer, oldFormat, newFormat)) {
483:                    return false;
484:                }
485:                if (oldFormat.isEntity() && oldFormat.isCurrentVersion()) {
486:                    String newClassName = newFormat.getClassName();
487:                    String oldClassName = oldFormat.getClassName();
488:                    /* Queue the renaming of the primary and secondary databases. */
489:                    renameDbs.put(Store
490:                            .makePriDbName(storePrefix, oldClassName), Store
491:                            .makePriDbName(storePrefix, newClassName));
492:                    for (SecondaryKeyMetadata keyMeta : oldFormat
493:                            .getEntityMetadata().getSecondaryKeys().values()) {
494:                        String keyName = keyMeta.getKeyName();
495:                        renameDbs.put(Store.makeSecDbName(storePrefix,
496:                                oldClassName, keyName), Store.makeSecDbName(
497:                                storePrefix, newClassName, keyName));
498:                    }
499:                }
500:
501:                /*
502:                 * Link the old format to the renamed format so that we can detect the
503:                 * rename in useOldFormat.
504:                 */
505:                renameFormats.put(oldFormat, newFormat);
506:
507:                setFormatsChanged(oldFormat);
508:                return true;
509:            }
510:
511:            /**
512:             * Called by ComplexFormat when a secondary key name is changed.
513:             */
514:            void renameSecondaryDatabase(Format oldFormat, Format newFormat,
515:                    String oldKeyName, String newKeyName) {
516:                renameDbs.put(Store.makeSecDbName(storePrefix, oldFormat
517:                        .getClassName(), oldKeyName), Store.makeSecDbName(
518:                        storePrefix, newFormat.getClassName(), newKeyName));
519:            }
520:
521:            private boolean applyDeleter(Deleter deleter, Format oldFormat,
522:                    Format newFormat) {
523:                if (!checkUpdatedVersion(deleter, oldFormat, newFormat)) {
524:                    return false;
525:                }
526:                if (oldFormat.isEntity() && oldFormat.isCurrentVersion()) {
527:                    /* Queue the deletion of the primary and secondary databases. */
528:                    String className = oldFormat.getClassName();
529:                    deleteDbs.add(Store.makePriDbName(storePrefix, className));
530:                    for (SecondaryKeyMetadata keyMeta : oldFormat
531:                            .getEntityMetadata().getSecondaryKeys().values()) {
532:                        deleteDbs.add(Store.makeSecDbName(storePrefix,
533:                                className, keyMeta.getKeyName()));
534:                    }
535:                }
536:
537:                /*
538:                 * Set the format to deleted last,  so that the above test using
539:                 * isCurrentVersion works properly.
540:                 */
541:                oldFormat.setDeleted(true);
542:                if (newFormat != null) {
543:                    oldFormat.setLatestVersion(newFormat);
544:                }
545:
546:                setFormatsChanged(oldFormat);
547:                return true;
548:            }
549:
550:            /**
551:             * Called by ComplexFormat when a secondary key is dropped.
552:             */
553:            void deleteSecondaryDatabase(Format oldFormat, String keyName) {
554:                deleteDbs.add(Store.makeSecDbName(storePrefix, oldFormat
555:                        .getClassName(), keyName));
556:            }
557:
558:            private boolean applyConverter(Converter converter,
559:                    Format oldFormat, Format newFormat) {
560:                if (!checkUpdatedVersion(converter, oldFormat, newFormat)) {
561:                    return false;
562:                }
563:                Reader reader = new ConverterReader(converter);
564:                useEvolvedFormat(oldFormat, reader, newFormat);
565:                return true;
566:            }
567:
568:            boolean isClassConverted(Format format) {
569:                return format.getReader() instanceof  ConverterReader;
570:            }
571:
572:            private boolean checkUpdatedVersion(Mutation mutation,
573:                    Format oldFormat, Format newFormat) {
574:                if (newFormat != null && !oldFormat.isEnum()
575:                        && newFormat.getVersion() <= oldFormat.getVersion()) {
576:                    addInvalidMutation(oldFormat, newFormat, mutation,
577:                            "A new higher version number must be assigned");
578:                    return false;
579:                } else {
580:                    return true;
581:                }
582:            }
583:
584:            boolean checkUpdatedVersion(String scenario, Format oldFormat,
585:                    Format newFormat) {
586:                if (newFormat != null && !oldFormat.isEnum()
587:                        && newFormat.getVersion() <= oldFormat.getVersion()) {
588:                    addEvolveError(oldFormat, newFormat, scenario,
589:                            "A new higher version number must be assigned");
590:                    return false;
591:                } else {
592:                    return true;
593:                }
594:            }
595:
596:            void renameAndRemoveDatabases(Environment env, Transaction txn)
597:                    throws DatabaseException {
598:
599:                for (String dbName : deleteDbs) {
600:                    try {
601:                        env.removeDatabase(txn, dbName);
602:                    } catch (DatabaseNotFoundException ignored) {
603:                    }
604:                }
605:                for (Map.Entry<String, String> entry : renameDbs.entrySet()) {
606:                    try {
607:                        env.renameDatabase(txn, entry.getKey(), entry
608:                                .getValue());
609:                    } catch (DatabaseNotFoundException ignored) {
610:                    }
611:                }
612:            }
613:
614:            /**
615:             * Evolves a primary key field or composite key field.
616:             */
617:            int evolveRequiredKeyField(Format oldParent, Format newParent,
618:                    FieldInfo oldField, FieldInfo newField) {
619:                int result = EVOLVE_NONE;
620:                String oldName = oldField.getName();
621:                final String FIELD_KIND = "primary key field or composite key class field";
622:                final String FIELD_LABEL = FIELD_KIND + ": " + oldName;
623:
624:                if (newField == null) {
625:                    addMissingMutation(oldParent, newParent,
626:                            "Field is missing and deletion is not allowed for a "
627:                                    + FIELD_LABEL);
628:                    return EVOLVE_FAILURE;
629:                }
630:
631:                /* Check field mutations.  Only a Renamer is allowed. */
632:                Deleter deleter = mutations.getDeleter(
633:                        oldParent.getClassName(), oldParent.getVersion(),
634:                        oldName);
635:                if (deleter != null) {
636:                    addInvalidMutation(oldParent, newParent, deleter,
637:                            "Deleter is not allowed for a " + FIELD_LABEL);
638:                    return EVOLVE_FAILURE;
639:                }
640:                Converter converter = mutations.getConverter(oldParent
641:                        .getClassName(), oldParent.getVersion(), oldName);
642:                if (converter != null) {
643:                    addInvalidMutation(oldParent, newParent, converter,
644:                            "Converter is not allowed for a " + FIELD_LABEL);
645:                    return EVOLVE_FAILURE;
646:                }
647:                Renamer renamer = mutations.getRenamer(
648:                        oldParent.getClassName(), oldParent.getVersion(),
649:                        oldName);
650:                String newName = newField.getName();
651:                if (renamer != null) {
652:                    if (!renamer.getNewName().equals(newName)) {
653:                        addInvalidMutation(oldParent, newParent, converter,
654:                                "Converter is not allowed for a " + FIELD_LABEL);
655:                        return EVOLVE_FAILURE;
656:                    }
657:                    result = EVOLVE_NEEDED;
658:                } else {
659:                    if (!oldName.equals(newName)) {
660:                        addMissingMutation(oldParent, newParent,
661:                                "Renamer is required when field name is changed from: "
662:                                        + oldName + " to: " + newName);
663:                        return EVOLVE_FAILURE;
664:                    }
665:                }
666:
667:                /*
668:                 * Evolve the declared version of the field format.
669:                 */
670:                Format oldFieldFormat = oldField.getType();
671:                if (!evolveFormat(oldFieldFormat)) {
672:                    return EVOLVE_FAILURE;
673:                }
674:                Format oldLatestFormat = oldFieldFormat.getLatestVersion();
675:                Format newFieldFormat = newField.getType();
676:
677:                if (oldLatestFormat.getClassName().equals(
678:                        newFieldFormat.getClassName())) {
679:                    /* Formats are identical. */
680:                    return result;
681:                } else if ((oldLatestFormat.getWrapperFormat() != null && oldLatestFormat
682:                        .getWrapperFormat().getId() == newFieldFormat.getId())
683:                        || (newFieldFormat.getWrapperFormat() != null && newFieldFormat
684:                                .getWrapperFormat().getId() == oldLatestFormat
685:                                .getId())) {
686:                    /* Primitive <-> primitive wrapper type change. */
687:                    return EVOLVE_NEEDED;
688:                } else {
689:                    /* Type was changed incompatibly. */
690:                    addEvolveError(oldParent, newParent,
691:                            "Type may not be changed for a " + FIELD_KIND,
692:                            "Old field type: " + oldLatestFormat.getClassName()
693:                                    + " is not compatible with the new type: "
694:                                    + newFieldFormat.getClassName()
695:                                    + " for field: " + oldName);
696:                    return EVOLVE_FAILURE;
697:                }
698:            }
699:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.