Source Code Cross Referenced for ComplexFormat.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) 


0001:        /*-
0002:         * See the file LICENSE for redistribution information.
0003:         *
0004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
0005:         *
0006:         * $Id: ComplexFormat.java,v 1.30.2.7 2008/01/07 15:14:19 cwl Exp $
0007:         */
0008:
0009:        package com.sleepycat.persist.impl;
0010:
0011:        import java.io.Serializable;
0012:        import java.util.ArrayList;
0013:        import java.util.Collections;
0014:        import java.util.HashMap;
0015:        import java.util.HashSet;
0016:        import java.util.IdentityHashMap;
0017:        import java.util.List;
0018:        import java.util.Map;
0019:        import java.util.Set;
0020:
0021:        import com.sleepycat.persist.evolve.Converter;
0022:        import com.sleepycat.persist.evolve.Deleter;
0023:        import com.sleepycat.persist.evolve.EntityConverter;
0024:        import com.sleepycat.persist.evolve.Mutations;
0025:        import com.sleepycat.persist.evolve.Renamer;
0026:        import com.sleepycat.persist.model.ClassMetadata;
0027:        import com.sleepycat.persist.model.EntityMetadata;
0028:        import com.sleepycat.persist.model.FieldMetadata;
0029:        import com.sleepycat.persist.model.Relationship;
0030:        import com.sleepycat.persist.model.SecondaryKeyMetadata;
0031:        import com.sleepycat.persist.raw.RawField;
0032:        import com.sleepycat.persist.raw.RawObject;
0033:
0034:        /**
0035:         * Format for persistent complex classes that are not composite key classes.
0036:         * This includes entity classes and subclasses.
0037:         *
0038:         * @author Mark Hayes
0039:         */
0040:        public class ComplexFormat extends Format {
0041:
0042:            private static final long serialVersionUID = -2847843033590454917L;
0043:
0044:            private ClassMetadata clsMeta;
0045:            private EntityMetadata entityMeta;
0046:            private FieldInfo priKeyField;
0047:            private List<FieldInfo> secKeyFields;
0048:            private List<FieldInfo> nonKeyFields;
0049:            private FieldReader secKeyFieldReader;
0050:            private FieldReader nonKeyFieldReader;
0051:            private Map<String, String> oldToNewKeyMap;
0052:            private Map<String, String> newToOldFieldMap;
0053:            private boolean evolveNeeded;
0054:            private transient Accessor objAccessor;
0055:            private transient Accessor rawAccessor;
0056:            private transient Format entityFormat;
0057:            private transient Map<String, FieldAddress> secKeyAddresses;
0058:            private transient volatile Map<String, RawField> rawFields;
0059:            private transient volatile FieldInfo[] rawInputFields;
0060:            private transient volatile int[] rawInputLevels;
0061:            private transient volatile int rawInputDepth;
0062:
0063:            ComplexFormat(Class cls, ClassMetadata clsMeta,
0064:                    EntityMetadata entityMeta) {
0065:                super (cls);
0066:                this .clsMeta = clsMeta;
0067:                this .entityMeta = entityMeta;
0068:                secKeyFields = new ArrayList<FieldInfo>();
0069:                nonKeyFields = FieldInfo.getInstanceFields(cls);
0070:
0071:                /*
0072:                 * Validate primary key metadata and move primary key field from
0073:                 * nonKeyFields to priKeyField.
0074:                 */
0075:                if (clsMeta.getPrimaryKey() != null) {
0076:                    String fieldName = clsMeta.getPrimaryKey().getName();
0077:                    FieldInfo field = FieldInfo.getField(nonKeyFields,
0078:                            fieldName);
0079:                    if (field == null) {
0080:                        throw new IllegalArgumentException(
0081:                                "Primary key field does not exist: "
0082:                                        + getClassName() + '.' + fieldName);
0083:                    }
0084:                    nonKeyFields.remove(field);
0085:                    priKeyField = field;
0086:                }
0087:
0088:                /*
0089:                 * Validate secondary key metadata and move secondary key fields from
0090:                 * nonKeyFields to secKeyFields.
0091:                 */
0092:                if (clsMeta.getSecondaryKeys() != null) {
0093:                    for (SecondaryKeyMetadata secKeyMeta : clsMeta
0094:                            .getSecondaryKeys().values()) {
0095:                        String fieldName = secKeyMeta.getName();
0096:                        FieldInfo field = FieldInfo.getField(nonKeyFields,
0097:                                fieldName);
0098:                        if (field == null) {
0099:                            throw new IllegalArgumentException(
0100:                                    "Secondary key field does not exist: "
0101:                                            + getClassName() + '.' + fieldName);
0102:                        }
0103:                        Class fieldCls = field.getFieldClass();
0104:                        Relationship rel = secKeyMeta.getRelationship();
0105:                        if (rel == Relationship.ONE_TO_MANY
0106:                                || rel == Relationship.MANY_TO_MANY) {
0107:                            if (!PersistKeyCreator.isManyType(fieldCls)) {
0108:                                throw new IllegalArgumentException(
0109:                                        "ONE_TO_MANY and MANY_TO_MANY keys must"
0110:                                                + " have an array or Collection type: "
0111:                                                + getClassName() + '.'
0112:                                                + fieldName);
0113:                            }
0114:                        } else {
0115:                            if (PersistKeyCreator.isManyType(fieldCls)) {
0116:                                throw new IllegalArgumentException(
0117:                                        "ONE_TO_ONE and MANY_TO_ONE keys must not"
0118:                                                + " have an array or Collection type: "
0119:                                                + getClassName() + '.'
0120:                                                + fieldName);
0121:                            }
0122:                        }
0123:                        nonKeyFields.remove(field);
0124:                        secKeyFields.add(field);
0125:                    }
0126:                }
0127:
0128:                /* Sort each group of fields by name. */
0129:                Collections.sort(secKeyFields);
0130:                Collections.sort(nonKeyFields);
0131:            }
0132:
0133:            @Override
0134:            void migrateFromBeta(Map<String, Format> formatMap) {
0135:                super .migrateFromBeta(formatMap);
0136:                if (priKeyField != null) {
0137:                    priKeyField.migrateFromBeta(formatMap);
0138:                }
0139:                for (FieldInfo field : secKeyFields) {
0140:                    field.migrateFromBeta(formatMap);
0141:                }
0142:                for (FieldInfo field : nonKeyFields) {
0143:                    field.migrateFromBeta(formatMap);
0144:                }
0145:            }
0146:
0147:            /**
0148:             * Returns getSuperFormat cast to ComplexFormat.  It is guaranteed that all
0149:             * super formats of a ComplexFormat are a ComplexFormat.
0150:             */
0151:            private ComplexFormat getComplexSuper() {
0152:                return (ComplexFormat) getSuperFormat();
0153:            }
0154:
0155:            /**
0156:             * Returns getLatestVersion cast to ComplexFormat.  It is guaranteed that
0157:             * all versions of a ComplexFormat are a ComplexFormat.
0158:             */
0159:            private ComplexFormat getComplexLatest() {
0160:                return (ComplexFormat) getLatestVersion();
0161:            }
0162:
0163:            String getPriKeyField() {
0164:                if (clsMeta.getPrimaryKey() != null) {
0165:                    return clsMeta.getPrimaryKey().getName();
0166:                } else {
0167:                    return null;
0168:                }
0169:            }
0170:
0171:            @Override
0172:            boolean isEntity() {
0173:                return clsMeta.isEntityClass();
0174:            }
0175:
0176:            @Override
0177:            boolean isModelClass() {
0178:                return true;
0179:            }
0180:
0181:            @Override
0182:            ClassMetadata getClassMetadata() {
0183:                return clsMeta;
0184:            }
0185:
0186:            @Override
0187:            EntityMetadata getEntityMetadata() {
0188:                return entityMeta;
0189:            }
0190:
0191:            @Override
0192:            Format getEntityFormat() {
0193:                if (isInitialized()) {
0194:                    return entityFormat;
0195:                } else {
0196:                    for (Format format = this ; format != null; format = format
0197:                            .getSuperFormat()) {
0198:                        if (format.isEntity()) {
0199:                            return format;
0200:                        }
0201:                    }
0202:                    return null;
0203:                }
0204:            }
0205:
0206:            @Override
0207:            void setEvolveNeeded(boolean needed) {
0208:                evolveNeeded = needed;
0209:            }
0210:
0211:            @Override
0212:            boolean getEvolveNeeded() {
0213:                return evolveNeeded;
0214:            }
0215:
0216:            @Override
0217:            public Map<String, RawField> getFields() {
0218:
0219:                /*
0220:                 * Synchronization is not required since rawFields is immutable.  If
0221:                 * by chance we create two maps when two threads execute this block, no
0222:                 * harm is done.  But be sure to assign the rawFields field only after
0223:                 * the map is fully populated.
0224:                 */
0225:                if (rawFields == null) {
0226:                    Map<String, RawField> map = new HashMap<String, RawField>();
0227:                    if (priKeyField != null) {
0228:                        map.put(priKeyField.getName(), priKeyField);
0229:                    }
0230:                    for (RawField field : secKeyFields) {
0231:                        map.put(field.getName(), field);
0232:                    }
0233:                    for (RawField field : nonKeyFields) {
0234:                        map.put(field.getName(), field);
0235:                    }
0236:                    rawFields = map;
0237:                }
0238:                return rawFields;
0239:            }
0240:
0241:            @Override
0242:            void collectRelatedFormats(Catalog catalog,
0243:                    Map<String, Format> newFormats) {
0244:                Class cls = getType();
0245:                /* Collect field formats. */
0246:                if (priKeyField != null) {
0247:                    priKeyField.collectRelatedFormats(catalog, newFormats);
0248:                }
0249:                for (FieldInfo field : secKeyFields) {
0250:                    field.collectRelatedFormats(catalog, newFormats);
0251:                }
0252:                for (FieldInfo field : nonKeyFields) {
0253:                    field.collectRelatedFormats(catalog, newFormats);
0254:                }
0255:                /* Collect TO_MANY secondary key field element class formats. */
0256:                if (entityMeta != null) {
0257:                    for (SecondaryKeyMetadata secKeyMeta : entityMeta
0258:                            .getSecondaryKeys().values()) {
0259:                        String elemClsName = secKeyMeta.getElementClassName();
0260:                        if (elemClsName != null) {
0261:                            Class elemCls = SimpleCatalog
0262:                                    .keyClassForName(elemClsName);
0263:                            catalog.createFormat(elemCls, newFormats);
0264:                        }
0265:                    }
0266:                }
0267:                /* Recursively collect superclass formats. */
0268:                Class super Cls = cls.getSuperclass();
0269:                if (super Cls != Object.class) {
0270:                    Format super Format = catalog.createFormat(super Cls,
0271:                            newFormats);
0272:                    if (!(super Format instanceof  ComplexFormat)) {
0273:                        throw new IllegalArgumentException(
0274:                                "The superclass of a complex type must not be a"
0275:                                        + " composite key class or a simple type class: "
0276:                                        + super Cls.getName());
0277:                    }
0278:                }
0279:                /* Collect proxied format. */
0280:                String proxiedClsName = clsMeta.getProxiedClassName();
0281:                if (proxiedClsName != null) {
0282:                    catalog.createFormat(proxiedClsName, newFormats);
0283:                }
0284:            }
0285:
0286:            @Override
0287:            void initialize(Catalog catalog, int initVersion) {
0288:                Class type = getType();
0289:                boolean useEnhanced = false;
0290:                if (type != null) {
0291:                    useEnhanced = EnhancedAccessor.isEnhanced(type);
0292:                }
0293:                /* Initialize all fields. */
0294:                if (priKeyField != null) {
0295:                    priKeyField.initialize(catalog, initVersion);
0296:                }
0297:                for (FieldInfo field : secKeyFields) {
0298:                    field.initialize(catalog, initVersion);
0299:                }
0300:                for (FieldInfo field : nonKeyFields) {
0301:                    field.initialize(catalog, initVersion);
0302:                }
0303:                /* Set the superclass format for a new (never initialized) format. */
0304:                ComplexFormat super Format = getComplexSuper();
0305:                if (type != null && super Format == null) {
0306:                    Class super Cls = type.getSuperclass();
0307:                    if (super Cls != Object.class) {
0308:                        super Format = (ComplexFormat) catalog
0309:                                .getFormat(super Cls.getName());
0310:                        setSuperFormat(super Format);
0311:                    }
0312:                }
0313:                /* Initialize the superclass format and validate the super accessor. */
0314:                if (super Format != null) {
0315:                    super Format.initializeIfNeeded(catalog);
0316:                    Accessor super Accessor = super Format.objAccessor;
0317:                    if (type != null && super Accessor != null) {
0318:                        if (useEnhanced) {
0319:                            if (!(super Accessor instanceof  EnhancedAccessor)) {
0320:                                throw new IllegalStateException(
0321:                                        "The superclass of an enhanced class must also "
0322:                                                + "be enhanced: "
0323:                                                + getClassName() + " extends "
0324:                                                + super Format.getClassName());
0325:                            }
0326:                        } else {
0327:                            if (!(super Accessor instanceof  ReflectionAccessor)) {
0328:                                throw new IllegalStateException(
0329:                                        "The superclass of an unenhanced class must "
0330:                                                + "not be enhanced: "
0331:                                                + getClassName() + " extends "
0332:                                                + super Format.getClassName());
0333:                            }
0334:                        }
0335:                    }
0336:                }
0337:                /* Find entity format, if any. */
0338:                for (Format format = this ; format != null; format = format
0339:                        .getSuperFormat()) {
0340:                    if (format.isEntity()) {
0341:                        entityFormat = format;
0342:                        break;
0343:                    }
0344:                }
0345:                /* Create the accessors. */
0346:                if (type != null) {
0347:                    if (useEnhanced) {
0348:                        objAccessor = new EnhancedAccessor(catalog, type, this );
0349:                    } else {
0350:                        Accessor super ObjAccessor = (super Format != null) ? super Format.objAccessor
0351:                                : null;
0352:                        objAccessor = new ReflectionAccessor(catalog, type,
0353:                                super ObjAccessor, priKeyField, secKeyFields,
0354:                                nonKeyFields);
0355:                    }
0356:                }
0357:                Accessor super RawAccessor = (super Format != null) ? super Format.rawAccessor
0358:                        : null;
0359:                rawAccessor = new RawAccessor(this , super RawAccessor,
0360:                        priKeyField, secKeyFields, nonKeyFields);
0361:
0362:                /* Initialize secondary key field addresses. */
0363:                EntityMetadata latestEntityMeta = null;
0364:                if (entityFormat != null) {
0365:                    latestEntityMeta = entityFormat.getLatestVersion()
0366:                            .getEntityMetadata();
0367:                }
0368:                if (latestEntityMeta != null) {
0369:                    secKeyAddresses = new HashMap<String, FieldAddress>();
0370:                    ComplexFormat this Latest = getComplexLatest();
0371:                    if (this Latest != this ) {
0372:                        this Latest.initializeIfNeeded(catalog);
0373:                    }
0374:                    nextKeyLoop: for (SecondaryKeyMetadata secKeyMeta : latestEntityMeta
0375:                            .getSecondaryKeys().values()) {
0376:                        String clsName = secKeyMeta.getDeclaringClassName();
0377:                        String fieldName = secKeyMeta.getName();
0378:                        int super Level = 0;
0379:                        for (ComplexFormat format = this ; format != null; format = format
0380:                                .getComplexSuper()) {
0381:                            if (clsName.equals(format.getLatestVersion()
0382:                                    .getClassName())) {
0383:                                String useFieldName = null;
0384:                                if (format.newToOldFieldMap != null
0385:                                        && format.newToOldFieldMap
0386:                                                .containsKey(fieldName)) {
0387:                                    useFieldName = format.newToOldFieldMap
0388:                                            .get(fieldName);
0389:                                } else {
0390:                                    useFieldName = fieldName;
0391:                                }
0392:                                boolean isSecField;
0393:                                int fieldNum;
0394:                                FieldInfo info = FieldInfo.getField(
0395:                                        format.secKeyFields, useFieldName);
0396:                                if (info != null) {
0397:                                    isSecField = true;
0398:                                    fieldNum = format.secKeyFields
0399:                                            .indexOf(info);
0400:                                } else {
0401:                                    isSecField = false;
0402:                                    info = FieldInfo.getField(
0403:                                            format.nonKeyFields, useFieldName);
0404:                                    if (info == null) {
0405:                                        /* Field not present in old format. */
0406:                                        assert this Latest != this ;
0407:                                        this Latest
0408:                                                .checkNewSecKeyInitializer(secKeyMeta);
0409:                                        continue nextKeyLoop;
0410:                                    }
0411:                                    fieldNum = format.nonKeyFields
0412:                                            .indexOf(info);
0413:                                }
0414:                                FieldAddress addr = new FieldAddress(
0415:                                        isSecField, fieldNum, super Level,
0416:                                        format, info.getType());
0417:                                secKeyAddresses.put(secKeyMeta.getKeyName(),
0418:                                        addr);
0419:                            }
0420:                            super Level += 1;
0421:                        }
0422:                    }
0423:                }
0424:            }
0425:
0426:            /**
0427:             * Checks that the type of a new secondary key is not a primitive and that
0428:             * the default contructor does not initialize it to a non-null value.
0429:             */
0430:            private void checkNewSecKeyInitializer(
0431:                    SecondaryKeyMetadata secKeyMeta) {
0432:                if (objAccessor != null) {
0433:                    FieldAddress addr = secKeyAddresses.get(secKeyMeta
0434:                            .getKeyName());
0435:                    Object obj = objAccessor.newInstance();
0436:                    Object val = objAccessor.getField(obj, addr.fieldNum,
0437:                            addr.super Level, addr.isSecField);
0438:                    if (val != null) {
0439:                        if (addr.keyFormat.isPrimitive()) {
0440:                            throw new IllegalArgumentException(
0441:                                    "For a new secondary key field the field type must "
0442:                                            + "not be a primitive -- class: "
0443:                                            + secKeyMeta
0444:                                                    .getDeclaringClassName()
0445:                                            + " field: " + secKeyMeta.getName());
0446:                        } else {
0447:                            throw new IllegalArgumentException(
0448:                                    "For a new secondary key field the default "
0449:                                            + "constructor must not initialize the field to a "
0450:                                            + "non-null value -- class: "
0451:                                            + secKeyMeta
0452:                                                    .getDeclaringClassName()
0453:                                            + " field: " + secKeyMeta.getName());
0454:                        }
0455:                    }
0456:                }
0457:            }
0458:
0459:            private boolean nullOrEqual(Object o1, Object o2) {
0460:                if (o1 == null) {
0461:                    return o2 == null;
0462:                } else {
0463:                    return o1.equals(o2);
0464:                }
0465:            }
0466:
0467:            @Override
0468:            Object newArray(int len) {
0469:                return objAccessor.newArray(len);
0470:            }
0471:
0472:            @Override
0473:            public Object newInstance(EntityInput input, boolean rawAccess) {
0474:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0475:                return accessor.newInstance();
0476:            }
0477:
0478:            @Override
0479:            public Object readObject(Object o, EntityInput input,
0480:                    boolean rawAccess) {
0481:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0482:                accessor.readSecKeyFields(o, input, 0, Accessor.MAX_FIELD_NUM,
0483:                        -1);
0484:                accessor.readNonKeyFields(o, input, 0, Accessor.MAX_FIELD_NUM,
0485:                        -1);
0486:                return o;
0487:            }
0488:
0489:            @Override
0490:            void writeObject(Object o, EntityOutput output, boolean rawAccess) {
0491:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0492:                accessor.writeSecKeyFields(o, output);
0493:                accessor.writeNonKeyFields(o, output);
0494:            }
0495:
0496:            @Override
0497:            Object convertRawObject(Catalog catalog, boolean rawAccess,
0498:                    RawObject rawObject, IdentityHashMap converted) {
0499:                /*
0500:                 * Synchronization is not required since rawInputFields, rawInputLevels
0501:                 * and rawInputDepth are immutable.  If by chance we create duplicate
0502:                 * values when two threads execute this block, no harm is done.  But be
0503:                 * sure to assign the fields only after the values are fully populated.
0504:                 */
0505:                FieldInfo[] fields = rawInputFields;
0506:                int[] levels = rawInputLevels;
0507:                int depth = rawInputDepth;
0508:                if (fields == null || levels == null || depth == 0) {
0509:
0510:                    /*
0511:                     * The volatile fields are not yet set.  Prepare to process the
0512:                     * class hierarchy, storing class formats in order from the highest
0513:                     * superclass down to the current class.
0514:                     */
0515:                    depth = 0;
0516:                    int nFields = 0;
0517:                    for (ComplexFormat format = this ; format != null; format = format
0518:                            .getComplexSuper()) {
0519:                        nFields += format.getNFields();
0520:                        depth += 1;
0521:                    }
0522:                    ComplexFormat[] hierarchy = new ComplexFormat[depth];
0523:                    int level = depth;
0524:                    for (ComplexFormat format = this ; format != null; format = format
0525:                            .getComplexSuper()) {
0526:                        level -= 1;
0527:                        hierarchy[level] = format;
0528:                    }
0529:                    assert level == 0;
0530:
0531:                    /* Populate levels and fields in parallel. */
0532:                    levels = new int[nFields];
0533:                    fields = new FieldInfo[nFields];
0534:                    int index = 0;
0535:
0536:                    /*
0537:                     * The primary key is the first field read/written.  We use the
0538:                     * first primary key field encountered going from this class upward
0539:                     * in the class hierarchy.
0540:                     */
0541:                    if (getEntityFormat() != null) {
0542:                        for (level = depth - 1; level >= 0; level -= 1) {
0543:                            ComplexFormat format = hierarchy[level];
0544:                            if (format.priKeyField != null) {
0545:                                levels[index] = level;
0546:                                fields[index] = format.priKeyField;
0547:                                index += 1;
0548:                                break;
0549:                            }
0550:                        }
0551:                        assert index == 1;
0552:                    }
0553:
0554:                    /*
0555:                     * Secondary key fields are read/written next, from the highest
0556:                     * base class downward.
0557:                     */
0558:                    for (level = 0; level < depth; level += 1) {
0559:                        ComplexFormat format = hierarchy[level];
0560:                        for (FieldInfo field : format.secKeyFields) {
0561:                            levels[index] = level;
0562:                            fields[index] = field;
0563:                            index += 1;
0564:                        }
0565:                    }
0566:
0567:                    /*
0568:                     * Other fields are read/written last, from the highest base class
0569:                     * downward.
0570:                     */
0571:                    for (level = 0; level < depth; level += 1) {
0572:                        ComplexFormat format = hierarchy[level];
0573:                        for (FieldInfo field : format.nonKeyFields) {
0574:                            levels[index] = level;
0575:                            fields[index] = field;
0576:                            index += 1;
0577:                        }
0578:                    }
0579:
0580:                    /* We're finished -- update the volatile fields for next time. */
0581:                    assert index == fields.length;
0582:                    rawInputFields = fields;
0583:                    rawInputLevels = levels;
0584:                    rawInputDepth = depth;
0585:                }
0586:
0587:                /*
0588:                 * Create an objects array that is parallel to the fields and levels
0589:                 * arrays, but contains the RawObject for each slot from which the
0590:                 * field value can be retrieved.  The predetermined level for each
0591:                 * field determines which RawObject in the instance hierarchy to use.
0592:                 */
0593:                RawObject[] objectsByLevel = new RawObject[depth];
0594:                int level = depth;
0595:                for (RawObject raw = rawObject; raw != null; raw = raw
0596:                        .getSuper()) {
0597:                    if (level == 0) {
0598:                        throw new IllegalArgumentException(
0599:                                "RawObject has too many superclasses: "
0600:                                        + rawObject.getType().getClassName());
0601:                    }
0602:                    level -= 1;
0603:                    objectsByLevel[level] = raw;
0604:                }
0605:                if (level > 0) {
0606:                    throw new IllegalArgumentException(
0607:                            "RawObject has too few superclasses: "
0608:                                    + rawObject.getType().getClassName());
0609:                }
0610:                assert level == 0;
0611:                RawObject[] objects = new RawObject[fields.length];
0612:                for (int i = 0; i < objects.length; i += 1) {
0613:                    objects[i] = objectsByLevel[levels[i]];
0614:                }
0615:
0616:                /* Create the persistent object and convert all RawObject fields. */
0617:                EntityInput in = new RawComplexInput(catalog, rawAccess,
0618:                        converted, fields, objects);
0619:                Object o = newInstance(in, rawAccess);
0620:                converted.put(rawObject, o);
0621:                if (getEntityFormat() != null) {
0622:                    readPriKey(o, in, rawAccess);
0623:                }
0624:                return readObject(o, in, rawAccess);
0625:            }
0626:
0627:            @Override
0628:            boolean isPriKeyNullOrZero(Object o, boolean rawAccess) {
0629:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0630:                return accessor.isPriKeyFieldNullOrZero(o);
0631:            }
0632:
0633:            @Override
0634:            void writePriKey(Object o, EntityOutput output, boolean rawAccess) {
0635:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0636:                accessor.writePriKeyField(o, output);
0637:            }
0638:
0639:            @Override
0640:            public void readPriKey(Object o, EntityInput input,
0641:                    boolean rawAccess) {
0642:                Accessor accessor = rawAccess ? rawAccessor : objAccessor;
0643:                accessor.readPriKeyField(o, input);
0644:            }
0645:
0646:            @Override
0647:            boolean nullifySecKey(Catalog catalog, Object entity,
0648:                    String keyName, Object keyElement) {
0649:                if (secKeyAddresses == null) {
0650:                    throw new IllegalStateException();
0651:                }
0652:                FieldAddress addr = secKeyAddresses.get(keyName);
0653:                if (addr != null) {
0654:                    Object oldVal = rawAccessor.getField(entity, addr.fieldNum,
0655:                            addr.super Level, addr.isSecField);
0656:                    if (oldVal != null) {
0657:                        if (keyElement != null) {
0658:                            RawObject container = (RawObject) oldVal;
0659:                            Object[] a1 = container.getElements();
0660:                            boolean isArray = (a1 != null);
0661:                            if (!isArray) {
0662:                                a1 = CollectionProxy.getElements(container);
0663:                            }
0664:                            if (a1 != null) {
0665:                                for (int i = 0; i < a1.length; i += 1) {
0666:                                    if (keyElement.equals(a1[i])) {
0667:                                        int len = a1.length - 1;
0668:                                        Object[] a2 = new Object[len];
0669:                                        System.arraycopy(a1, 0, a2, 0, i);
0670:                                        System.arraycopy(a1, i + 1, a2, i, len
0671:                                                - i);
0672:                                        if (isArray) {
0673:                                            rawAccessor.setField(entity,
0674:                                                    addr.fieldNum,
0675:                                                    addr.super Level,
0676:                                                    addr.isSecField,
0677:                                                    new RawObject(container
0678:                                                            .getType(), a2));
0679:                                        } else {
0680:                                            CollectionProxy.setElements(
0681:                                                    container, a2);
0682:                                        }
0683:                                        return true;
0684:                                    }
0685:                                }
0686:                            }
0687:                            return false;
0688:                        } else {
0689:                            rawAccessor.setField(entity, addr.fieldNum,
0690:                                    addr.super Level, addr.isSecField, null);
0691:                            return true;
0692:                        }
0693:                    } else {
0694:                        return false;
0695:                    }
0696:                } else {
0697:                    return false;
0698:                }
0699:            }
0700:
0701:            @Override
0702:            void skipContents(RecordInput input) {
0703:                skipToSecKeyField(input, Accessor.MAX_FIELD_NUM);
0704:                skipToNonKeyField(input, Accessor.MAX_FIELD_NUM);
0705:            }
0706:
0707:            @Override
0708:            void copySecMultiKey(RecordInput input, Format keyFormat,
0709:                    Set results) {
0710:                CollectionProxy.copyElements(input, this , keyFormat, results);
0711:            }
0712:
0713:            @Override
0714:            Format skipToSecKey(RecordInput input, String keyName) {
0715:                if (secKeyAddresses == null) {
0716:                    throw new IllegalStateException();
0717:                }
0718:                FieldAddress addr = secKeyAddresses.get(keyName);
0719:                if (addr != null) {
0720:                    if (addr.isSecField) {
0721:                        addr.clsFormat.skipToSecKeyField(input, addr.fieldNum);
0722:                    } else {
0723:                        skipToSecKeyField(input, Accessor.MAX_FIELD_NUM);
0724:                        addr.clsFormat.skipToNonKeyField(input, addr.fieldNum);
0725:                    }
0726:                    return addr.keyFormat;
0727:                } else {
0728:                    return null;
0729:                }
0730:            }
0731:
0732:            private int getNFields() {
0733:                return ((priKeyField != null) ? 1 : 0) + secKeyFields.size()
0734:                        + nonKeyFields.size();
0735:            }
0736:
0737:            private void skipToSecKeyField(RecordInput input, int toFieldNum) {
0738:                ComplexFormat super Format = getComplexSuper();
0739:                if (super Format != null) {
0740:                    super Format
0741:                            .skipToSecKeyField(input, Accessor.MAX_FIELD_NUM);
0742:                }
0743:                int maxNum = Math.min(secKeyFields.size(), toFieldNum);
0744:                for (int i = 0; i < maxNum; i += 1) {
0745:                    input.skipField(secKeyFields.get(i).getType());
0746:                }
0747:            }
0748:
0749:            private void skipToNonKeyField(RecordInput input, int toFieldNum) {
0750:                ComplexFormat super Format = getComplexSuper();
0751:                if (super Format != null) {
0752:                    super Format
0753:                            .skipToNonKeyField(input, Accessor.MAX_FIELD_NUM);
0754:                }
0755:                int maxNum = Math.min(nonKeyFields.size(), toFieldNum);
0756:                for (int i = 0; i < maxNum; i += 1) {
0757:                    input.skipField(nonKeyFields.get(i).getType());
0758:                }
0759:            }
0760:
0761:            private static class FieldAddress {
0762:
0763:                boolean isSecField;
0764:                int fieldNum;
0765:                int super Level;
0766:                ComplexFormat clsFormat;
0767:                Format keyFormat;
0768:
0769:                FieldAddress(boolean isSecField, int fieldNum, int super Level,
0770:                        ComplexFormat clsFormat, Format keyFormat) {
0771:                    this .isSecField = isSecField;
0772:                    this .fieldNum = fieldNum;
0773:                    this .super Level = super Level;
0774:                    this .clsFormat = clsFormat;
0775:                    this .keyFormat = keyFormat;
0776:                }
0777:            }
0778:
0779:            @Override
0780:            boolean evolve(Format newFormatParam, Evolver evolver) {
0781:
0782:                /* Disallow evolution to a non-complex format. */
0783:                if (!(newFormatParam instanceof  ComplexFormat)) {
0784:                    evolver.addMissingMutation(this , newFormatParam,
0785:                            "Converter is required when a complex type is changed "
0786:                                    + "to a simple type or enum type");
0787:                    return false;
0788:                }
0789:                ComplexFormat newFormat = (ComplexFormat) newFormatParam;
0790:                Mutations mutations = evolver.getMutations();
0791:                boolean this Changed = false;
0792:                boolean super Changed = false;
0793:                Map<String, String> allKeyNameMap = new HashMap<String, String>();
0794:
0795:                /*
0796:                 * Evolve all superclass formats, even when a deleted class appears in
0797:                 * the hierarchy.  This ensures that the super format's
0798:                 * getLatestVersion/getComplexLatest method can be used accurately
0799:                 * below.
0800:                 */
0801:                for (ComplexFormat oldSuper = getComplexSuper(); oldSuper != null; oldSuper = oldSuper
0802:                        .getComplexSuper()) {
0803:                    Converter converter = mutations.getConverter(oldSuper
0804:                            .getClassName(), oldSuper.getVersion(), null);
0805:                    if (converter != null) {
0806:                        evolver
0807:                                .addMissingMutation(
0808:                                        this ,
0809:                                        newFormatParam,
0810:                                        "Converter is required for this subclass when a "
0811:                                                + "Converter appears on its superclass: "
0812:                                                + converter);
0813:                        return false;
0814:                    }
0815:                    if (!evolver.evolveFormat(oldSuper)) {
0816:                        return false;
0817:                    }
0818:                    if (!oldSuper.isCurrentVersion()) {
0819:                        if (oldSuper.isDeleted()) {
0820:                            if (!oldSuper.evolveDeletedClass(evolver)) {
0821:                                return false;
0822:                            }
0823:                        }
0824:                        if (oldSuper.oldToNewKeyMap != null) {
0825:                            allKeyNameMap.putAll(oldSuper.oldToNewKeyMap);
0826:                        }
0827:                        super Changed = true;
0828:                    }
0829:                }
0830:
0831:                /*
0832:                 * Compare the old and new class hierarhies and decide whether each
0833:                 * change is allowed or not:
0834:                 * + Old deleted and removed superclass -- allowed
0835:                 * + Old empty and removed superclass -- allowed
0836:                 * + Old non-empty and removed superclass -- not allowed
0837:                 * + Old superclass repositioned in the hierarchy -- not allowed
0838:                 * + New inserted superclass -- allowed
0839:                 */
0840:                Class newFormatCls = newFormat.getExistingType();
0841:                Class newSuper = newFormatCls;
0842:                List<Integer> newLevels = new ArrayList<Integer>();
0843:                int newLevel = 0;
0844:                newLevels.add(newLevel);
0845:
0846:                /*
0847:                 * When this format has a new superclass, we treat it as a change to
0848:                 * this format as well as to the superclass hierarchy.
0849:                 */
0850:                if (getSuperFormat() == null) {
0851:                    if (newFormatCls.getSuperclass() != Object.class) {
0852:                        this Changed = true;
0853:                        super Changed = true;
0854:                    }
0855:                } else {
0856:                    if (!getSuperFormat().getLatestVersion().getClassName()
0857:                            .equals(newFormatCls.getSuperclass().getName())) {
0858:                        this Changed = true;
0859:                        super Changed = true;
0860:                    }
0861:                }
0862:
0863:                for (ComplexFormat oldSuper = getComplexSuper(); oldSuper != null; oldSuper = oldSuper
0864:                        .getComplexSuper()) {
0865:
0866:                    /* Find the matching superclass in the new hierarchy. */
0867:                    String oldSuperName = oldSuper.getLatestVersion()
0868:                            .getClassName();
0869:                    Class foundNewSuper = null;
0870:                    int tryNewLevel = newLevel;
0871:                    for (Class newSuper2 = newSuper.getSuperclass(); newSuper2 != Object.class; newSuper2 = newSuper2
0872:                            .getSuperclass()) {
0873:                        tryNewLevel += 1;
0874:                        if (oldSuperName.equals(newSuper2.getName())) {
0875:                            foundNewSuper = newSuper2;
0876:                            newLevel = tryNewLevel;
0877:                            break;
0878:                        }
0879:                    }
0880:
0881:                    if (foundNewSuper != null) {
0882:
0883:                        /*
0884:                         * We found the old superclass in the new hierarchy.  Traverse
0885:                         * through the superclass formats that were skipped over above
0886:                         * when finding it.
0887:                         */
0888:                        for (Class newSuper2 = newSuper.getSuperclass(); newSuper2 != foundNewSuper; newSuper2 = newSuper2
0889:                                .getSuperclass()) {
0890:
0891:                            /*
0892:                             * The class hierarchy changed -- a new class was inserted.
0893:                             */
0894:                            super Changed = true;
0895:
0896:                            /*
0897:                             * Check that the new formats skipped over above are not at
0898:                             * a different position in the old hierarchy.
0899:                             */
0900:                            for (ComplexFormat oldSuper2 = oldSuper
0901:                                    .getComplexSuper(); oldSuper2 != null; oldSuper2 = oldSuper2
0902:                                    .getComplexSuper()) {
0903:                                String oldSuper2Name = oldSuper2
0904:                                        .getLatestVersion().getClassName();
0905:                                if (oldSuper2Name.equals(newSuper2.getName())) {
0906:                                    evolver
0907:                                            .addMissingMutation(
0908:                                                    this ,
0909:                                                    newFormatParam,
0910:                                                    "Class Converter is required when a "
0911:                                                            + "superclass is moved in the class "
0912:                                                            + "hierarchy: "
0913:                                                            + newSuper2
0914:                                                                    .getName());
0915:                                    return false;
0916:                                }
0917:                            }
0918:                        }
0919:                        newSuper = foundNewSuper;
0920:                        newLevels.add(newLevel);
0921:                    } else {
0922:
0923:                        /*
0924:                         * We did not find the old superclass in the new hierarchy.
0925:                         * The class hierarchy changed, since an old class no longer
0926:                         * appears.
0927:                         */
0928:                        super Changed = true;
0929:
0930:                        /* Check that the old class can be safely removed. */
0931:                        if (!oldSuper.isDeleted()) {
0932:                            ComplexFormat oldSuperLatest = oldSuper
0933:                                    .getComplexLatest();
0934:                            if (oldSuperLatest.getNFields() != 0) {
0935:                                evolver
0936:                                        .addMissingMutation(
0937:                                                this ,
0938:                                                newFormatParam,
0939:                                                "When a superclass is removed from the class "
0940:                                                        + "hierarchy, the superclass or all of its "
0941:                                                        + "persistent fields must be deleted with a "
0942:                                                        + "Deleter: "
0943:                                                        + oldSuperLatest
0944:                                                                .getClassName());
0945:                                return false;
0946:                            }
0947:                        }
0948:
0949:                        if (isEntity() && isCurrentVersion()) {
0950:                            Map<String, SecondaryKeyMetadata> secKeys = oldSuper.clsMeta
0951:                                    .getSecondaryKeys();
0952:                            for (FieldInfo field : oldSuper.secKeyFields) {
0953:                                SecondaryKeyMetadata meta = secKeys.get(field
0954:                                        .getName());
0955:                                assert meta != null;
0956:                                allKeyNameMap.put(meta.getKeyName(), null);
0957:                            }
0958:                        }
0959:
0960:                        /*
0961:                         * Add the DO_NOT_READ_ACCESSOR level to prevent an empty class
0962:                         * (no persistent fields) from being read via the Accessor.
0963:                         */
0964:                        newLevels.add(EvolveReader.DO_NOT_READ_ACCESSOR);
0965:                    }
0966:                }
0967:
0968:                /* Make FieldReaders for this format if needed. */
0969:                int result = evolveAllFields(newFormat, evolver);
0970:                if (result == Evolver.EVOLVE_FAILURE) {
0971:                    return false;
0972:                }
0973:                if (result == Evolver.EVOLVE_NEEDED) {
0974:                    this Changed = true;
0975:                }
0976:                if (oldToNewKeyMap != null) {
0977:                    allKeyNameMap.putAll(oldToNewKeyMap);
0978:                }
0979:
0980:                /* Require new version number if this class was changed. */
0981:                if (this Changed
0982:                        && !evolver
0983:                                .checkUpdatedVersion(
0984:                                        "Changes to the fields or superclass were detected",
0985:                                        this , newFormat)) {
0986:                    return false;
0987:                }
0988:
0989:                /* Rename the secondary databases. */
0990:                if (allKeyNameMap.size() > 0 && isEntity()
0991:                        && isCurrentVersion()) {
0992:                    for (Map.Entry<String, String> entry : allKeyNameMap
0993:                            .entrySet()) {
0994:                        String oldKeyName = entry.getKey();
0995:                        String newKeyName = entry.getValue();
0996:                        if (newKeyName != null) {
0997:                            evolver.renameSecondaryDatabase(this , newFormat,
0998:                                    oldKeyName, newKeyName);
0999:                        } else {
1000:                            evolver.deleteSecondaryDatabase(this , oldKeyName);
1001:                        }
1002:                    }
1003:                }
1004:
1005:                /* Use an EvolveReader if needed. */
1006:                if (super Changed || this Changed) {
1007:                    Reader reader = new EvolveReader(newLevels);
1008:                    evolver.useEvolvedFormat(this , reader, newFormat);
1009:                } else {
1010:                    evolver.useOldFormat(this , newFormat);
1011:                }
1012:                return true;
1013:            }
1014:
1015:            @Override
1016:            boolean evolveMetadata(Format newFormatParam, Converter converter,
1017:                    Evolver evolver) {
1018:                assert !isDeleted();
1019:                assert isEntity();
1020:                assert newFormatParam.isEntity();
1021:                ComplexFormat newFormat = (ComplexFormat) newFormatParam;
1022:
1023:                if (!checkKeyTypeChange(newFormat, entityMeta.getPrimaryKey(),
1024:                        newFormat.entityMeta.getPrimaryKey(), "primary key",
1025:                        evolver)) {
1026:                    return false;
1027:                }
1028:
1029:                Set<String> deletedKeys;
1030:                if (converter instanceof  EntityConverter) {
1031:                    EntityConverter entityConverter = (EntityConverter) converter;
1032:                    deletedKeys = entityConverter.getDeletedKeys();
1033:                } else {
1034:                    deletedKeys = Collections.emptySet();
1035:                }
1036:
1037:                Map<String, SecondaryKeyMetadata> oldSecondaryKeys = entityMeta
1038:                        .getSecondaryKeys();
1039:                Map<String, SecondaryKeyMetadata> newSecondaryKeys = newFormat.entityMeta
1040:                        .getSecondaryKeys();
1041:                Set<String> insertedKeys = new HashSet<String>(newSecondaryKeys
1042:                        .keySet());
1043:
1044:                for (SecondaryKeyMetadata oldMeta : oldSecondaryKeys.values()) {
1045:                    String keyName = oldMeta.getKeyName();
1046:                    if (deletedKeys.contains(keyName)) {
1047:                        if (isCurrentVersion()) {
1048:                            evolver.deleteSecondaryDatabase(this , keyName);
1049:                        }
1050:                    } else {
1051:                        SecondaryKeyMetadata newMeta = newSecondaryKeys
1052:                                .get(keyName);
1053:                        if (newMeta == null) {
1054:                            evolver.addInvalidMutation(this , newFormat,
1055:                                    converter,
1056:                                    "Existing key not found in new entity metadata: "
1057:                                            + keyName);
1058:                            return false;
1059:                        }
1060:                        insertedKeys.remove(keyName);
1061:                        String keyLabel = "secondary key: " + keyName;
1062:                        if (!checkKeyTypeChange(newFormat, oldMeta, newMeta,
1063:                                keyLabel, evolver)) {
1064:                            return false;
1065:                        }
1066:                        if (!checkSecKeyMetadata(newFormat, oldMeta, newMeta,
1067:                                evolver)) {
1068:                            return false;
1069:                        }
1070:                    }
1071:                }
1072:
1073:                if (!insertedKeys.isEmpty()) {
1074:                    evolver
1075:                            .addEvolveError(
1076:                                    this ,
1077:                                    newFormat,
1078:                                    "Error",
1079:                                    "New keys "
1080:                                            + insertedKeys
1081:                                            + " not allowed when using a Converter with an entity class");
1082:                }
1083:
1084:                return true;
1085:            }
1086:
1087:            /**
1088:             * Checks that changes to secondary key metadata are legal.
1089:             */
1090:            private boolean checkSecKeyMetadata(Format newFormat,
1091:                    SecondaryKeyMetadata oldMeta, SecondaryKeyMetadata newMeta,
1092:                    Evolver evolver) {
1093:                if (oldMeta.getRelationship() != newMeta.getRelationship()) {
1094:                    evolver.addEvolveError(this , newFormat,
1095:                            "Change detected in the relate attribute (Relationship) "
1096:                                    + "of a secondary key", "Old key: "
1097:                                    + oldMeta.getKeyName() + " relate: "
1098:                                    + oldMeta.getRelationship() + " new key: "
1099:                                    + newMeta.getKeyName() + " relate: "
1100:                                    + newMeta.getRelationship());
1101:                    return false;
1102:                }
1103:                return true;
1104:            }
1105:
1106:            /**
1107:             * Checks that the type of a key field did not change, as known from
1108:             * metadata when a class conversion is used.
1109:             */
1110:            private boolean checkKeyTypeChange(Format newFormat,
1111:                    FieldMetadata oldMeta, FieldMetadata newMeta,
1112:                    String keyLabel, Evolver evolver) {
1113:                String oldClass = oldMeta.getClassName();
1114:                String newClass = newMeta.getClassName();
1115:                if (!oldClass.equals(newClass)) {
1116:                    SimpleCatalog catalog = SimpleCatalog.getInstance();
1117:                    Format oldType = catalog.getFormat(oldClass);
1118:                    Format newType = catalog.getFormat(newClass);
1119:                    if (oldType == null
1120:                            || newType == null
1121:                            || ((oldType.getWrapperFormat() == null || oldType
1122:                                    .getWrapperFormat().getId() != newType
1123:                                    .getId()) && (newType.getWrapperFormat() == null || newType
1124:                                    .getWrapperFormat().getId() != oldType
1125:                                    .getId()))) {
1126:                        evolver
1127:                                .addEvolveError(
1128:                                        this ,
1129:                                        newFormat,
1130:                                        "Type change detected for " + keyLabel,
1131:                                        "Old field type: "
1132:                                                + oldClass
1133:                                                + " is not compatible with the new type: "
1134:                                                + newClass + " old field: "
1135:                                                + oldMeta.getName()
1136:                                                + " new field: "
1137:                                                + newMeta.getName());
1138:                        return false;
1139:                    }
1140:                }
1141:                return true;
1142:            }
1143:
1144:            /**
1145:             * Special case for creating FieldReaders for a deleted class when it
1146:             * appears in the class hierarchy of its non-deleted subclass.
1147:             */
1148:            private boolean evolveDeletedClass(Evolver evolver) {
1149:                assert isDeleted();
1150:                if (secKeyFieldReader == null || nonKeyFieldReader == null) {
1151:                    if (priKeyField != null && getEntityFormat() != null
1152:                            && !getEntityFormat().isDeleted()) {
1153:                        evolver
1154:                                .addEvolveError(
1155:                                        this ,
1156:                                        this ,
1157:                                        "Class containing primary key field was deleted ",
1158:                                        "Primary key is needed in an entity class hierarchy: "
1159:                                                + priKeyField.getName());
1160:                        return false;
1161:                    } else {
1162:                        secKeyFieldReader = new SkipFieldReader(0, secKeyFields);
1163:                        nonKeyFieldReader = new SkipFieldReader(0, nonKeyFields);
1164:                        return true;
1165:                    }
1166:                } else {
1167:                    return true;
1168:                }
1169:            }
1170:
1171:            /**
1172:             * Creates a FieldReader for secondary key fields and non-key fields if
1173:             * necessary.  Checks the primary key field if necessary.  Does not evolve
1174:             * superclass format fields.
1175:             */
1176:            private int evolveAllFields(ComplexFormat newFormat, Evolver evolver) {
1177:
1178:                assert !isDeleted();
1179:                secKeyFieldReader = null;
1180:                nonKeyFieldReader = null;
1181:                oldToNewKeyMap = null;
1182:
1183:                /* Evolve primary key field. */
1184:                boolean evolveFailure = false;
1185:                boolean evolveNeeded = false;
1186:                if (priKeyField != null) {
1187:                    int result = evolver.evolveRequiredKeyField(this ,
1188:                            newFormat, priKeyField, newFormat.priKeyField);
1189:                    if (result == Evolver.EVOLVE_FAILURE) {
1190:                        evolveFailure = true;
1191:                    } else if (result == Evolver.EVOLVE_NEEDED) {
1192:                        evolveNeeded = true;
1193:                    }
1194:                }
1195:
1196:                /* Evolve secondary key fields. */
1197:                FieldReader reader = evolveFieldList(secKeyFields,
1198:                        newFormat.secKeyFields, true, newFormat.nonKeyFields,
1199:                        newFormat, evolver);
1200:                if (reader == FieldReader.EVOLVE_FAILURE) {
1201:                    evolveFailure = true;
1202:                } else if (reader != null) {
1203:                    evolveNeeded = true;
1204:                }
1205:                if (reader != FieldReader.EVOLVE_NEEDED) {
1206:                    secKeyFieldReader = reader;
1207:                }
1208:
1209:                /* Evolve non-key fields. */
1210:                reader = evolveFieldList(nonKeyFields, newFormat.nonKeyFields,
1211:                        false, newFormat.secKeyFields, newFormat, evolver);
1212:                if (reader == FieldReader.EVOLVE_FAILURE) {
1213:                    evolveFailure = true;
1214:                } else if (reader != null) {
1215:                    evolveNeeded = true;
1216:                }
1217:                if (reader != FieldReader.EVOLVE_NEEDED) {
1218:                    nonKeyFieldReader = reader;
1219:                }
1220:
1221:                /* Return result. */
1222:                if (evolveFailure) {
1223:                    return Evolver.EVOLVE_FAILURE;
1224:                } else if (evolveNeeded) {
1225:                    return Evolver.EVOLVE_NEEDED;
1226:                } else {
1227:                    return Evolver.EVOLVE_NONE;
1228:                }
1229:            }
1230:
1231:            /**
1232:             * Returns a FieldReader that reads no fields.
1233:             *
1234:             * Instead of adding a DoNothingFieldReader class, we use a
1235:             * MultiFieldReader with an empty field list.  We do not add a new
1236:             * FieldReader class to avoid changing the catalog format.  [#15524]
1237:             */
1238:            private FieldReader getDoNothingFieldReader() {
1239:                List<FieldReader> emptyList = Collections.emptyList();
1240:                return new MultiFieldReader(emptyList);
1241:            }
1242:
1243:            /**
1244:             * Evolves a list of fields, either secondary key or non-key fields, for a
1245:             * single class format.
1246:             *
1247:             * @return a FieldReader if field evolution is needed, null if no evolution
1248:             * is needed, or FieldReader.EVOLVE_FAILURE if an evolution error occurs.
1249:             */
1250:            private FieldReader evolveFieldList(List<FieldInfo> oldFields,
1251:                    List<FieldInfo> newFields, boolean isOldSecKeyField,
1252:                    List<FieldInfo> otherNewFields, ComplexFormat newFormat,
1253:                    Evolver evolver) {
1254:                Mutations mutations = evolver.getMutations();
1255:                boolean evolveFailure = false;
1256:                boolean evolveNeeded = false;
1257:                boolean readerNeeded = false;
1258:                List<FieldReader> fieldReaders = new ArrayList<FieldReader>();
1259:                FieldReader currentReader = null;
1260:                int prevNewFieldIndex = newFields.size();
1261:                int newFieldsMatched = 0;
1262:
1263:                /*
1264:                 * Add FieldReaders to the list in old field storage order, since that
1265:                 * is the order in which field values must be read.
1266:                 */
1267:                fieldLoop: for (int oldFieldIndex = 0; oldFieldIndex < oldFields
1268:                        .size(); oldFieldIndex += 1) {
1269:
1270:                    FieldInfo oldField = oldFields.get(oldFieldIndex);
1271:                    String oldName = oldField.getName();
1272:                    SecondaryKeyMetadata oldMeta = null;
1273:                    if (isOldSecKeyField) {
1274:                        oldMeta = clsMeta.getSecondaryKeys().get(oldName);
1275:                        assert oldMeta != null;
1276:                    }
1277:
1278:                    /* Get field mutations. */
1279:                    Renamer renamer = mutations.getRenamer(getClassName(),
1280:                            getVersion(), oldName);
1281:                    Deleter deleter = mutations.getDeleter(getClassName(),
1282:                            getVersion(), oldName);
1283:                    Converter converter = mutations.getConverter(
1284:                            getClassName(), getVersion(), oldName);
1285:                    if (deleter != null
1286:                            && (converter != null || renamer != null)) {
1287:                        evolver.addInvalidMutation(this , newFormat, deleter,
1288:                                "Field Deleter is not allowed along with a Renamer or "
1289:                                        + "Converter for the same field: "
1290:                                        + oldName);
1291:                        evolveFailure = true;
1292:                        continue fieldLoop;
1293:                    }
1294:
1295:                    /*
1296:                     * Match old and new field by name, taking into account the Renamer
1297:                     * mutation.  If the @SecondaryKey annotation was added or removed,
1298:                     * the field will have moved from one of the two field lists to the
1299:                     * other.
1300:                     */
1301:                    String newName = (renamer != null) ? renamer.getNewName()
1302:                            : oldName;
1303:                    if (!oldName.equals(newName)) {
1304:                        if (newToOldFieldMap == null) {
1305:                            newToOldFieldMap = new HashMap<String, String>();
1306:                        }
1307:                        newToOldFieldMap.put(newName, oldName);
1308:                    }
1309:                    int newFieldIndex = FieldInfo.getFieldIndex(newFields,
1310:                            newName);
1311:                    FieldInfo newField = null;
1312:                    boolean isNewSecKeyField = isOldSecKeyField;
1313:                    if (newFieldIndex >= 0) {
1314:                        newField = newFields.get(newFieldIndex);
1315:                    } else {
1316:                        newFieldIndex = FieldInfo.getFieldIndex(otherNewFields,
1317:                                newName);
1318:                        if (newFieldIndex >= 0) {
1319:                            newField = otherNewFields.get(newFieldIndex);
1320:                            isNewSecKeyField = !isOldSecKeyField;
1321:                        }
1322:                        evolveNeeded = true;
1323:                        readerNeeded = true;
1324:                    }
1325:
1326:                    /* Apply field Deleter and continue. */
1327:                    if (deleter != null) {
1328:                        if (newField != null) {
1329:                            evolver.addInvalidMutation(this , newFormat,
1330:                                    deleter,
1331:                                    "Field Deleter is not allowed when the persistent "
1332:                                            + "field is still present: "
1333:                                            + oldName);
1334:                            evolveFailure = true;
1335:                        }
1336:                        /* A SkipFieldReader can read multiple sequential fields. */
1337:                        if (currentReader instanceof  SkipFieldReader
1338:                                && currentReader.acceptField(oldFieldIndex,
1339:                                        newFieldIndex, isNewSecKeyField)) {
1340:                            currentReader.addField(oldField);
1341:                        } else {
1342:                            currentReader = new SkipFieldReader(oldFieldIndex,
1343:                                    oldField);
1344:                            fieldReaders.add(currentReader);
1345:                            readerNeeded = true;
1346:                            evolveNeeded = true;
1347:                        }
1348:                        if (isOldSecKeyField) {
1349:                            if (oldToNewKeyMap == null) {
1350:                                oldToNewKeyMap = new HashMap<String, String>();
1351:                            }
1352:                            oldToNewKeyMap.put(oldMeta.getKeyName(), null);
1353:                        }
1354:                        continue fieldLoop;
1355:                    } else {
1356:                        if (newField == null) {
1357:                            evolver.addMissingMutation(this , newFormat,
1358:                                    "Field is not present or not persistent: "
1359:                                            + oldName);
1360:                            evolveFailure = true;
1361:                            continue fieldLoop;
1362:                        }
1363:                    }
1364:
1365:                    /*
1366:                     * The old field corresponds to a known new field, and no Deleter
1367:                     * mutation applies.
1368:                     */
1369:                    newFieldsMatched += 1;
1370:
1371:                    /* Get and process secondary key metadata changes. */
1372:                    SecondaryKeyMetadata newMeta = null;
1373:                    if (isOldSecKeyField && isNewSecKeyField) {
1374:                        newMeta = newFormat.clsMeta.getSecondaryKeys().get(
1375:                                newName);
1376:                        assert newMeta != null;
1377:
1378:                        /* Validate metadata changes. */
1379:                        if (!checkSecKeyMetadata(newFormat, oldMeta, newMeta,
1380:                                evolver)) {
1381:                            evolveFailure = true;
1382:                            continue fieldLoop;
1383:                        }
1384:
1385:                        /*
1386:                         * Check for a renamed key and save the old-to-new mapping for
1387:                         * use in renaming the secondary database and for key
1388:                         * extraction.
1389:                         */
1390:                        String oldKeyName = oldMeta.getKeyName();
1391:                        String newKeyName = newMeta.getKeyName();
1392:                        if (!oldKeyName.equals(newKeyName)) {
1393:                            if (oldToNewKeyMap == null) {
1394:                                oldToNewKeyMap = new HashMap<String, String>();
1395:                            }
1396:                            oldToNewKeyMap.put(oldName, newName);
1397:                            evolveNeeded = true;
1398:                        }
1399:                    } else if (isOldSecKeyField && !isNewSecKeyField) {
1400:                        if (oldToNewKeyMap == null) {
1401:                            oldToNewKeyMap = new HashMap<String, String>();
1402:                        }
1403:                        oldToNewKeyMap.put(oldMeta.getKeyName(), null);
1404:                    }
1405:
1406:                    /* Apply field Converter and continue. */
1407:                    if (converter != null) {
1408:                        if (isOldSecKeyField) {
1409:                            evolver.addInvalidMutation(this , newFormat,
1410:                                    converter,
1411:                                    "Field Converter is not allowed for secondary key "
1412:                                            + "fields: " + oldName);
1413:                            evolveFailure = true;
1414:                        } else {
1415:                            currentReader = new ConvertFieldReader(converter,
1416:                                    oldFieldIndex, newFieldIndex,
1417:                                    isNewSecKeyField);
1418:                            fieldReaders.add(currentReader);
1419:                            readerNeeded = true;
1420:                            evolveNeeded = true;
1421:                        }
1422:                        continue fieldLoop;
1423:                    }
1424:
1425:                    /*
1426:                     * Evolve the declared version of the field format and all versions
1427:                     * more recent, and the formats for all of their subclasses.  While
1428:                     * we're at it, check to see if all possible classes are converted.
1429:                     */
1430:                    boolean allClassesConverted = true;
1431:                    Format oldFieldFormat = oldField.getType();
1432:                    for (Format formatVersion = oldFieldFormat
1433:                            .getLatestVersion(); true; formatVersion = formatVersion
1434:                            .getPreviousVersion()) {
1435:                        assert formatVersion != null;
1436:                        if (!evolver.evolveFormat(formatVersion)) {
1437:                            evolveFailure = true;
1438:                            continue fieldLoop;
1439:                        }
1440:                        if (!formatVersion.isNew()
1441:                                && !evolver.isClassConverted(formatVersion)) {
1442:                            allClassesConverted = false;
1443:                        }
1444:                        Set<Format> subclassFormats = evolver
1445:                                .getSubclassFormats(formatVersion);
1446:                        if (subclassFormats != null) {
1447:                            for (Format format2 : subclassFormats) {
1448:                                if (!evolver.evolveFormat(format2)) {
1449:                                    evolveFailure = true;
1450:                                    continue fieldLoop;
1451:                                }
1452:                                if (!format2.isNew()
1453:                                        && !evolver.isClassConverted(format2)) {
1454:                                    allClassesConverted = false;
1455:                                }
1456:                            }
1457:                        }
1458:                        if (formatVersion == oldFieldFormat) {
1459:                            break;
1460:                        }
1461:                    }
1462:
1463:                    /*
1464:                     * Check for compatible field types and apply a field widener if
1465:                     * needed.  If no widener is needed, fall through and apply a
1466:                     * PlainFieldReader.
1467:                     */
1468:                    Format oldLatestFormat = oldFieldFormat.getLatestVersion();
1469:                    Format newFieldFormat = newField.getType();
1470:                    if (oldLatestFormat.getClassName().equals(
1471:                            newFieldFormat.getClassName())
1472:                            && !oldLatestFormat.isDeleted()) {
1473:                        /* Formats are identical.  Fall through. */
1474:                    } else if (allClassesConverted) {
1475:                        /* All old classes will be converted.  Fall through. */
1476:                        evolveNeeded = true;
1477:                    } else if (WidenerInput.isWideningSupported(
1478:                            oldLatestFormat, newFieldFormat, isOldSecKeyField)) {
1479:                        /* Apply field widener and continue. */
1480:                        currentReader = new WidenFieldReader(oldLatestFormat,
1481:                                newFieldFormat, newFieldIndex, isNewSecKeyField);
1482:                        fieldReaders.add(currentReader);
1483:                        readerNeeded = true;
1484:                        evolveNeeded = true;
1485:                        continue fieldLoop;
1486:                    } else {
1487:                        boolean refWidened = false;
1488:                        if (!newFieldFormat.isPrimitive()
1489:                                && !oldLatestFormat.isPrimitive()
1490:                                && !oldLatestFormat.isDeleted()
1491:                                && !evolver.isClassConverted(oldLatestFormat)) {
1492:                            Class oldCls = oldLatestFormat.getExistingType();
1493:                            Class newCls = newFieldFormat.getExistingType();
1494:                            if (newCls.isAssignableFrom(oldCls)) {
1495:                                refWidened = true;
1496:                            }
1497:                        }
1498:                        if (refWidened) {
1499:                            /* A reference type has been widened.  Fall through. */
1500:                            evolveNeeded = true;
1501:                        } else {
1502:                            /* Types are not compatible. */
1503:                            evolver
1504:                                    .addMissingMutation(
1505:                                            this ,
1506:                                            newFormat,
1507:                                            "Old field type: "
1508:                                                    + oldLatestFormat
1509:                                                            .getClassName()
1510:                                                    + " is not compatible with the new type: "
1511:                                                    + newFieldFormat
1512:                                                            .getClassName()
1513:                                                    + " for field: " + oldName);
1514:                            evolveFailure = true;
1515:                            continue fieldLoop;
1516:                        }
1517:                    }
1518:
1519:                    /*
1520:                     * Old to new field conversion is not needed or is automatic.  Read
1521:                     * fields as if no evolution is needed.  A PlainFieldReader can
1522:                     * read multiple sequential fields.
1523:                     */
1524:                    if (currentReader instanceof  PlainFieldReader
1525:                            && currentReader.acceptField(oldFieldIndex,
1526:                                    newFieldIndex, isNewSecKeyField)) {
1527:                        currentReader.addField(oldField);
1528:                    } else {
1529:                        currentReader = new PlainFieldReader(oldFieldIndex,
1530:                                newFieldIndex, isNewSecKeyField);
1531:                        fieldReaders.add(currentReader);
1532:                    }
1533:                }
1534:
1535:                /*
1536:                 * If there are new fields, then the old fields must be read using a
1537:                 * reader, even if the old field list is empty.  Using the accessor
1538:                 * directly will read fields in the wrong order and will read fields
1539:                 * that were moved between lists (when adding and dropping
1540:                 * @SecondaryKey).  [#15524]
1541:                 */
1542:                if (newFieldsMatched < newFields.size()) {
1543:                    evolveNeeded = true;
1544:                    readerNeeded = true;
1545:                }
1546:
1547:                if (evolveFailure) {
1548:                    return FieldReader.EVOLVE_FAILURE;
1549:                } else if (readerNeeded) {
1550:                    if (fieldReaders.size() == 0) {
1551:                        return getDoNothingFieldReader();
1552:                    } else if (fieldReaders.size() == 1) {
1553:                        return fieldReaders.get(0);
1554:                    } else {
1555:                        return new MultiFieldReader(fieldReaders);
1556:                    }
1557:                } else if (evolveNeeded) {
1558:                    return FieldReader.EVOLVE_NEEDED;
1559:                } else {
1560:                    return null;
1561:                }
1562:            }
1563:
1564:            /**
1565:             * Base class for all FieldReader subclasses.  A FieldReader reads one or
1566:             * more fields in the old format data, and may call the new format Accessor
1567:             * to set the field values.
1568:             */
1569:            private static abstract class FieldReader implements  Serializable {
1570:
1571:                static final FieldReader EVOLVE_NEEDED = new PlainFieldReader(
1572:                        0, 0, false);
1573:                static final FieldReader EVOLVE_FAILURE = new PlainFieldReader(
1574:                        0, 0, false);
1575:
1576:                private static final long serialVersionUID = 866041475399255164L;
1577:
1578:                FieldReader() {
1579:                }
1580:
1581:                void initialize(Catalog catalog, int initVersion,
1582:                        ComplexFormat oldParentFormat,
1583:                        ComplexFormat newParentFormat, boolean isOldSecKey) {
1584:                }
1585:
1586:                boolean acceptField(int oldFieldIndex, int newFieldIndex,
1587:                        boolean isNewSecKeyField) {
1588:                    return false;
1589:                }
1590:
1591:                void addField(FieldInfo oldField) {
1592:                    throw new UnsupportedOperationException();
1593:                }
1594:
1595:                abstract void readFields(Object o, EntityInput input,
1596:                        Accessor accessor, int super Level);
1597:            }
1598:
1599:            /**
1600:             * Reads a continguous block of fields that have the same format in the old
1601:             * and new formats.
1602:             */
1603:            private static class PlainFieldReader extends FieldReader {
1604:
1605:                private static final long serialVersionUID = 1795593463439931402L;
1606:
1607:                private int startField;
1608:                private int endField;
1609:                private boolean secKeyField;
1610:                private transient int endOldField;
1611:
1612:                PlainFieldReader(int oldFieldIndex, int newFieldIndex,
1613:                        boolean isNewSecKeyField) {
1614:                    endOldField = oldFieldIndex;
1615:                    startField = newFieldIndex;
1616:                    endField = newFieldIndex;
1617:                    secKeyField = isNewSecKeyField;
1618:                }
1619:
1620:                @Override
1621:                boolean acceptField(int oldFieldIndex, int newFieldIndex,
1622:                        boolean isNewSecKeyField) {
1623:                    return oldFieldIndex == endOldField + 1
1624:                            && newFieldIndex == endField + 1
1625:                            && secKeyField == isNewSecKeyField;
1626:                }
1627:
1628:                @Override
1629:                void addField(FieldInfo oldField) {
1630:                    endField += 1;
1631:                    endOldField += 1;
1632:                }
1633:
1634:                @Override
1635:                final void readFields(Object o, EntityInput input,
1636:                        Accessor accessor, int super Level) {
1637:                    if (secKeyField) {
1638:                        accessor.readSecKeyFields(o, input, startField,
1639:                                endField, super Level);
1640:                    } else {
1641:                        accessor.readNonKeyFields(o, input, startField,
1642:                                endField, super Level);
1643:                    }
1644:                }
1645:            }
1646:
1647:            /**
1648:             * Skips a continguous block of fields that exist in the old format but not
1649:             * in the new format.
1650:             */
1651:            private static class SkipFieldReader extends FieldReader {
1652:
1653:                private static final long serialVersionUID = -3060281692155253098L;
1654:
1655:                private List<Format> fieldFormats;
1656:                private transient int endField;
1657:
1658:                SkipFieldReader(int startField, List<FieldInfo> fields) {
1659:                    endField = startField + fields.size() - 1;
1660:                    fieldFormats = new ArrayList<Format>(fields.size());
1661:                    for (FieldInfo field : fields) {
1662:                        fieldFormats.add(field.getType());
1663:                    }
1664:                }
1665:
1666:                SkipFieldReader(int startField, FieldInfo oldField) {
1667:                    endField = startField;
1668:                    fieldFormats = new ArrayList<Format>();
1669:                    fieldFormats.add(oldField.getType());
1670:                }
1671:
1672:                @Override
1673:                boolean acceptField(int oldFieldIndex, int newFieldIndex,
1674:                        boolean isNewSecKeyField) {
1675:                    return oldFieldIndex == endField + 1;
1676:                }
1677:
1678:                @Override
1679:                void addField(FieldInfo oldField) {
1680:                    endField += 1;
1681:                    fieldFormats.add(oldField.getType());
1682:                }
1683:
1684:                @Override
1685:                final void readFields(Object o, EntityInput input,
1686:                        Accessor accessor, int super Level) {
1687:                    for (Format format : fieldFormats) {
1688:                        input.skipField(format);
1689:                    }
1690:                }
1691:            }
1692:
1693:            /**
1694:             * Converts a single field using a field Converter.
1695:             */
1696:            private static class ConvertFieldReader extends FieldReader {
1697:
1698:                private static final long serialVersionUID = 8736410481633998710L;
1699:
1700:                private Converter converter;
1701:                private int oldFieldNum;
1702:                private int fieldNum;
1703:                private boolean secKeyField;
1704:                private transient Format oldFormat;
1705:                private transient Format newFormat;
1706:
1707:                ConvertFieldReader(Converter converter, int oldFieldIndex,
1708:                        int newFieldIndex, boolean isNewSecKeyField) {
1709:                    this .converter = converter;
1710:                    oldFieldNum = oldFieldIndex;
1711:                    fieldNum = newFieldIndex;
1712:                    secKeyField = isNewSecKeyField;
1713:                }
1714:
1715:                @Override
1716:                void initialize(Catalog catalog, int initVersion,
1717:                        ComplexFormat oldParentFormat,
1718:                        ComplexFormat newParentFormat, boolean isOldSecKey) {
1719:
1720:                    /*
1721:                     * The oldFieldNum field was added as part of a bug fix.  If not
1722:                     * present in this version of the catalog, we assume it is equal to
1723:                     * the new field index.  The code prior to the bug fix assumes the
1724:                     * old and new fields have the same index. [#15797]
1725:                     */
1726:                    if (initVersion < 1) {
1727:                        oldFieldNum = fieldNum;
1728:                    }
1729:
1730:                    if (isOldSecKey) {
1731:                        oldFormat = oldParentFormat.secKeyFields.get(
1732:                                oldFieldNum).getType();
1733:                    } else {
1734:                        oldFormat = oldParentFormat.nonKeyFields.get(
1735:                                oldFieldNum).getType();
1736:                    }
1737:                    if (secKeyField) {
1738:                        newFormat = newParentFormat.secKeyFields.get(fieldNum)
1739:                                .getType();
1740:                    } else {
1741:                        newFormat = newParentFormat.nonKeyFields.get(fieldNum)
1742:                                .getType();
1743:                    }
1744:                }
1745:
1746:                @Override
1747:                final void readFields(Object o, EntityInput input,
1748:                        Accessor accessor, int super Level) {
1749:
1750:                    /* Create and read the old format instance in raw mode. */
1751:                    boolean currentRawMode = input.setRawAccess(true);
1752:                    Object value;
1753:                    try {
1754:                        if (oldFormat.isPrimitive()) {
1755:                            value = input.readKeyObject(oldFormat);
1756:                        } else {
1757:                            value = input.readObject();
1758:                        }
1759:                    } finally {
1760:                        input.setRawAccess(currentRawMode);
1761:                    }
1762:
1763:                    /* Convert the raw instance to the current format. */
1764:                    Catalog catalog = input.getCatalog();
1765:                    value = converter.getConversion().convert(value);
1766:
1767:                    /* Use a RawSingleInput to convert and type-check the value. */
1768:                    EntityInput rawInput = new RawSingleInput(catalog,
1769:                            currentRawMode, null, value, newFormat);
1770:
1771:                    if (secKeyField) {
1772:                        accessor.readSecKeyFields(o, rawInput, fieldNum,
1773:                                fieldNum, super Level);
1774:                    } else {
1775:                        accessor.readNonKeyFields(o, rawInput, fieldNum,
1776:                                fieldNum, super Level);
1777:                    }
1778:                }
1779:            }
1780:
1781:            /**
1782:             * Widens a single field using a field Converter.
1783:             */
1784:            private static class WidenFieldReader extends FieldReader {
1785:
1786:                private static final long serialVersionUID = -2054520670170407282L;
1787:
1788:                private int fromFormatId;
1789:                private int toFormatId;
1790:                private int fieldNum;
1791:                private boolean secKeyField;
1792:
1793:                WidenFieldReader(Format oldFormat, Format newFormat,
1794:                        int newFieldIndex, boolean isNewSecKeyField) {
1795:                    fromFormatId = oldFormat.getId();
1796:                    toFormatId = newFormat.getId();
1797:                    fieldNum = newFieldIndex;
1798:                    secKeyField = isNewSecKeyField;
1799:                }
1800:
1801:                @Override
1802:                final void readFields(Object o, EntityInput input,
1803:                        Accessor accessor, int super Level) {
1804:
1805:                    /* The Accessor reads the field value from a WidenerInput. */
1806:                    EntityInput widenerInput = new WidenerInput(input,
1807:                            fromFormatId, toFormatId);
1808:
1809:                    if (secKeyField) {
1810:                        accessor.readSecKeyFields(o, widenerInput, fieldNum,
1811:                                fieldNum, super Level);
1812:                    } else {
1813:                        accessor.readNonKeyFields(o, widenerInput, fieldNum,
1814:                                fieldNum, super Level);
1815:                    }
1816:                }
1817:            }
1818:
1819:            /**
1820:             * A FieldReader composed of other FieldReaders, and that calls them in
1821:             * sequence.  Used when more than one FieldReader is needed for a list of
1822:             * fields.
1823:             */
1824:            private static class MultiFieldReader extends FieldReader {
1825:
1826:                private static final long serialVersionUID = -6035976787562441473L;
1827:
1828:                private List<FieldReader> subReaders;
1829:
1830:                MultiFieldReader(List<FieldReader> subReaders) {
1831:                    this .subReaders = subReaders;
1832:                }
1833:
1834:                @Override
1835:                void initialize(Catalog catalog, int initVersion,
1836:                        ComplexFormat oldParentFormat,
1837:                        ComplexFormat newParentFormat, boolean isOldSecKey) {
1838:                    for (FieldReader reader : subReaders) {
1839:                        reader.initialize(catalog, initVersion,
1840:                                oldParentFormat, newParentFormat, isOldSecKey);
1841:                    }
1842:                }
1843:
1844:                @Override
1845:                final void readFields(Object o, EntityInput input,
1846:                        Accessor accessor, int super Level) {
1847:                    for (FieldReader reader : subReaders) {
1848:                        reader.readFields(o, input, accessor, super Level);
1849:                    }
1850:                }
1851:            }
1852:
1853:            /**
1854:             * The Reader for evolving ComplexFormat instances.  Reads the old format
1855:             * data one class (one level in the class hierarchy) at a time.  If an
1856:             * Accessor is used at a given level, the Accessor is used for the
1857:             * corresponding level in the new class hierarchy (classes may be
1858:             * inserted/deleted during evolution).  At each level, a FieldReader is
1859:             * called to evolve the secondary key and non-key lists of fields.
1860:             */
1861:            private static class EvolveReader implements  Reader {
1862:
1863:                static final int DO_NOT_READ_ACCESSOR = Integer.MAX_VALUE;
1864:
1865:                private static final long serialVersionUID = -1016140948306913283L;
1866:
1867:                private transient ComplexFormat newFormat;
1868:
1869:                /**
1870:                 * oldHierarchy contains the formats of the old class hierarchy in most
1871:                 * to least derived class order.
1872:                 */
1873:                private transient ComplexFormat[] oldHierarchy;
1874:
1875:                /**
1876:                 * newHierarchyLevels contains the corresponding level in the new
1877:                 * hierarchy for each format in oldHierarchy. newHierarchyLevels is
1878:                 * indexed by the oldHierarchy index.
1879:                 */
1880:                private int[] newHierarchyLevels;
1881:
1882:                EvolveReader(List<Integer> newHierarchyLevelsList) {
1883:                    int oldDepth = newHierarchyLevelsList.size();
1884:                    newHierarchyLevels = new int[oldDepth];
1885:                    newHierarchyLevelsList.toArray();
1886:                    for (int i = 0; i < oldDepth; i += 1) {
1887:                        newHierarchyLevels[i] = newHierarchyLevelsList.get(i);
1888:                    }
1889:                }
1890:
1891:                public void initializeReader(Catalog catalog, int initVersion,
1892:                        Format oldFormatParam) {
1893:
1894:                    ComplexFormat oldFormat = (ComplexFormat) oldFormatParam;
1895:                    newFormat = oldFormat.getComplexLatest();
1896:                    newFormat.initializeIfNeeded(catalog);
1897:
1898:                    /* Create newHierarchy array. */
1899:                    int newDepth = 0;
1900:                    for (Format format = newFormat; format != null; format = format
1901:                            .getSuperFormat()) {
1902:                        newDepth += 1;
1903:                    }
1904:                    ComplexFormat[] newHierarchy = new ComplexFormat[newDepth];
1905:                    int level = 0;
1906:                    for (ComplexFormat format = newFormat; format != null; format = format
1907:                            .getComplexSuper()) {
1908:                        newHierarchy[level] = format;
1909:                        level += 1;
1910:                    }
1911:                    assert level == newDepth;
1912:
1913:                    /* Create oldHierarchy array and initialize FieldReaders. */
1914:                    int oldDepth = newHierarchyLevels.length;
1915:                    oldHierarchy = new ComplexFormat[oldDepth];
1916:                    level = 0;
1917:                    for (ComplexFormat oldFormat2 = oldFormat; oldFormat2 != null; oldFormat2 = oldFormat2
1918:                            .getComplexSuper()) {
1919:                        oldHierarchy[level] = oldFormat2;
1920:                        int level2 = newHierarchyLevels[level];
1921:                        ComplexFormat newFormat2 = (level2 != DO_NOT_READ_ACCESSOR) ? newHierarchy[level2]
1922:                                : null;
1923:                        level += 1;
1924:                        if (oldFormat2.secKeyFieldReader != null) {
1925:                            oldFormat2.secKeyFieldReader.initialize(catalog,
1926:                                    initVersion, oldFormat2, newFormat2, true);
1927:                        }
1928:                        if (oldFormat2.nonKeyFieldReader != null) {
1929:                            oldFormat2.nonKeyFieldReader.initialize(catalog,
1930:                                    initVersion, oldFormat2, newFormat2, false);
1931:                        }
1932:                    }
1933:                    assert level == oldDepth;
1934:                }
1935:
1936:                public Object newInstance(EntityInput input, boolean rawAccess) {
1937:                    return newFormat.newInstance(input, rawAccess);
1938:                }
1939:
1940:                public void readPriKey(Object o, EntityInput input,
1941:                        boolean rawAccess) {
1942:                    /* No conversion necessary for primary keys. */
1943:                    newFormat.readPriKey(o, input, rawAccess);
1944:                }
1945:
1946:                public Object readObject(Object o, EntityInput input,
1947:                        boolean rawAccess) {
1948:
1949:                    /* Use the Accessor for the new format. */
1950:                    Accessor accessor = rawAccess ? newFormat.rawAccessor
1951:                            : newFormat.objAccessor;
1952:
1953:                    /* Read old format fields from the top-most class downward. */
1954:                    int maxMinusOne = oldHierarchy.length - 1;
1955:
1956:                    /* Read secondary key fields with the adjusted superclass level. */
1957:                    for (int i = maxMinusOne; i >= 0; i -= 1) {
1958:                        FieldReader reader = oldHierarchy[i].secKeyFieldReader;
1959:                        int newLevel = newHierarchyLevels[i];
1960:                        if (reader != null) {
1961:                            reader.readFields(o, input, accessor, newLevel);
1962:                        } else if (newLevel != DO_NOT_READ_ACCESSOR) {
1963:                            accessor.readSecKeyFields(o, input, 0,
1964:                                    Accessor.MAX_FIELD_NUM, newLevel);
1965:                        }
1966:                    }
1967:
1968:                    /* Read non-key fields with the adjusted superclass level. */
1969:                    for (int i = maxMinusOne; i >= 0; i -= 1) {
1970:                        FieldReader reader = oldHierarchy[i].nonKeyFieldReader;
1971:                        int newLevel = newHierarchyLevels[i];
1972:                        if (reader != null) {
1973:                            reader.readFields(o, input, accessor, newLevel);
1974:                        } else if (newLevel != DO_NOT_READ_ACCESSOR) {
1975:                            accessor.readNonKeyFields(o, input, 0,
1976:                                    Accessor.MAX_FIELD_NUM, newLevel);
1977:                        }
1978:                    }
1979:                    return o;
1980:                }
1981:            }
1982:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.