Source Code Cross Referenced for ClassMetadata.java in  » Database-DBMS » db4o-6.4 » com » db4o » internal » 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 » Database DBMS » db4o 6.4 » com.db4o.internal 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* Copyright (C) 2004 - 2007  db4objects Inc.  http://www.db4o.com
0002:
0003:        This file is part of the db4o open source object database.
0004:
0005:        db4o is free software; you can redistribute it and/or modify it under
0006:        the terms of version 2 of the GNU General Public License as published
0007:        by the Free Software Foundation and as clarified by db4objects' GPL 
0008:        interpretation policy, available at
0009:        http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
0010:        Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
0011:        Suite 350, San Mateo, CA 94403, USA.
0012:
0013:        db4o is distributed in the hope that it will be useful, but WITHOUT ANY
0014:        WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:        for more details.
0017:
0018:        You should have received a copy of the GNU General Public License along
0019:        with this program; if not, write to the Free Software Foundation, Inc.,
0020:        59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
0021:        package com.db4o.internal;
0022:
0023:        import java.io.IOException;
0024:
0025:        import com.db4o.*;
0026:        import com.db4o.config.*;
0027:        import com.db4o.ext.*;
0028:        import com.db4o.foundation.*;
0029:        import com.db4o.internal.classindex.*;
0030:        import com.db4o.internal.diagnostic.*;
0031:        import com.db4o.internal.handlers.*;
0032:        import com.db4o.internal.marshall.*;
0033:        import com.db4o.internal.query.processor.*;
0034:        import com.db4o.internal.slots.*;
0035:        import com.db4o.marshall.*;
0036:        import com.db4o.query.*;
0037:        import com.db4o.reflect.*;
0038:        import com.db4o.reflect.generic.*;
0039:
0040:        /**
0041:         * @exclude
0042:         */
0043:        public class ClassMetadata extends PersistentBase implements 
0044:                IndexableTypeHandler, FirstClassHandler, StoredClass {
0045:
0046:            public ClassMetadata i_ancestor;
0047:
0048:            private Config4Class i_config;
0049:            public int _metaClassID;
0050:
0051:            public FieldMetadata[] i_fields;
0052:
0053:            private final ClassIndexStrategy _index;
0054:
0055:            protected String i_name;
0056:
0057:            private final ObjectContainerBase _container;
0058:
0059:            byte[] i_nameBytes;
0060:            private Buffer i_reader;
0061:
0062:            private boolean _classIndexed;
0063:
0064:            private ReflectClass _reflector;
0065:
0066:            private boolean _isEnum;
0067:
0068:            private EventDispatcher _eventDispatcher;
0069:
0070:            private boolean _internal;
0071:
0072:            private boolean _unversioned;
0073:
0074:            // for indexing purposes.
0075:            // TODO: check race conditions, upon multiple calls against the same class
0076:            private int i_lastID;
0077:
0078:            private TernaryBool _canUpdateFast = TernaryBool.UNSPECIFIED;
0079:
0080:            public final ObjectContainerBase stream() {
0081:                return _container;
0082:            }
0083:
0084:            public final boolean canUpdateFast() {
0085:                return _canUpdateFast.booleanValue(checkCanUpdateFast());
0086:            }
0087:
0088:            private final boolean checkCanUpdateFast() {
0089:                if (i_ancestor != null && !i_ancestor.canUpdateFast()) {
0090:                    return false;
0091:                }
0092:                if (i_config != null
0093:                        && i_config.cascadeOnDelete() == TernaryBool.YES) {
0094:                    return false;
0095:                }
0096:                for (int i = 0; i < i_fields.length; ++i) {
0097:                    if (i_fields[i].hasIndex()) {
0098:                        return false;
0099:                    }
0100:                }
0101:                return true;
0102:            }
0103:
0104:            boolean isInternal() {
0105:                return _internal;
0106:            }
0107:
0108:            private ClassIndexStrategy createIndexStrategy() {
0109:                return new BTreeClassIndexStrategy(this );
0110:            }
0111:
0112:            ClassMetadata(ObjectContainerBase container, ReflectClass reflector) {
0113:                _container = container;
0114:                _reflector = reflector;
0115:                _index = createIndexStrategy();
0116:                _classIndexed = true;
0117:            }
0118:
0119:            void activateFields(Transaction trans, Object obj, int depth) {
0120:                if (objectCanActivate(trans, obj)) {
0121:                    activateFieldsLoop(trans, obj, depth);
0122:                }
0123:            }
0124:
0125:            private final void activateFieldsLoop(Transaction trans,
0126:                    Object obj, int depth) {
0127:                for (int i = 0; i < i_fields.length; i++) {
0128:                    i_fields[i].cascadeActivation(trans, obj, depth, true);
0129:                }
0130:                if (i_ancestor != null) {
0131:                    i_ancestor.activateFieldsLoop(trans, obj, depth);
0132:                }
0133:            }
0134:
0135:            public final void addFieldIndices(StatefulBuffer a_writer,
0136:                    Slot oldSlot) {
0137:                if (hasClassIndex() || hasVirtualAttributes()) {
0138:                    ObjectHeader oh = new ObjectHeader(_container, this ,
0139:                            a_writer);
0140:                    oh._marshallerFamily._object.addFieldIndices(this ,
0141:                            oh._headerAttributes, a_writer, oldSlot);
0142:                }
0143:            }
0144:
0145:            void addMembers(ObjectContainerBase container) {
0146:                bitTrue(Const4.CHECKED_CHANGES);
0147:                if (installTranslator(container)) {
0148:                    return;
0149:                }
0150:
0151:                if (container.detectSchemaChanges()) {
0152:                    boolean dirty = isDirty();
0153:
0154:                    Collection4 members = new Collection4();
0155:
0156:                    if (null != i_fields) {
0157:                        members.addAll(i_fields);
0158:                        if (i_fields.length == 1
0159:                                && i_fields[0] instanceof  TranslatedFieldMetadata) {
0160:                            setStateOK();
0161:                            return;
0162:                        }
0163:                    }
0164:                    if (generateVersionNumbers()) {
0165:                        if (!hasVersionField()) {
0166:                            members.add(container.versionIndex());
0167:                            dirty = true;
0168:                        }
0169:                    }
0170:                    if (generateUUIDs()) {
0171:                        if (!hasUUIDField()) {
0172:                            members.add(container.uUIDIndex());
0173:                            dirty = true;
0174:                        }
0175:                    }
0176:                    dirty = collectReflectFields(container, members) | dirty;
0177:                    if (dirty) {
0178:                        _container.setDirtyInSystemTransaction(this );
0179:                        i_fields = new FieldMetadata[members.size()];
0180:                        members.toArray(i_fields);
0181:                        for (int i = 0; i < i_fields.length; i++) {
0182:                            i_fields[i].setArrayPosition(i);
0183:                        }
0184:                    } else {
0185:                        if (members.size() == 0) {
0186:                            i_fields = new FieldMetadata[0];
0187:                        }
0188:                    }
0189:
0190:                    DiagnosticProcessor dp = _container._handlers._diagnosticProcessor;
0191:                    if (dp.enabled()) {
0192:                        dp.checkClassHasFields(this );
0193:                    }
0194:
0195:                } else {
0196:                    if (i_fields == null) {
0197:                        i_fields = new FieldMetadata[0];
0198:                    }
0199:                }
0200:                _container.callbacks().classOnRegistered(this );
0201:                setStateOK();
0202:            }
0203:
0204:            private boolean collectReflectFields(ObjectContainerBase container,
0205:                    Collection4 collectedFields) {
0206:                boolean dirty = false;
0207:                ReflectField[] fields = reflectFields();
0208:                for (int i = 0; i < fields.length; i++) {
0209:                    if (storeField(fields[i])) {
0210:                        ClassMetadata fieldClassMetadata = container._handlers
0211:                                .classMetadataForClass(container, fields[i]
0212:                                        .getFieldType());
0213:                        if (fieldClassMetadata == null) {
0214:                            continue;
0215:                        }
0216:                        TypeHandler4 handler = fieldClassMetadata.typeHandler();
0217:                        FieldMetadata field = new FieldMetadata(this ,
0218:                                fields[i], handler, fieldClassMetadata.getID());
0219:                        boolean found = false;
0220:                        Iterator4 m = collectedFields.iterator();
0221:                        while (m.moveNext()) {
0222:                            if (((FieldMetadata) m.current()).equals(field)) {
0223:                                found = true;
0224:                                break;
0225:                            }
0226:                        }
0227:                        if (found) {
0228:                            continue;
0229:                        }
0230:                        dirty = true;
0231:                        collectedFields.add(field);
0232:                    }
0233:                }
0234:                return dirty;
0235:            }
0236:
0237:            private boolean installTranslator(ObjectContainerBase ocb) {
0238:                ObjectTranslator ot = getTranslator();
0239:                if (ot == null) {
0240:                    return false;
0241:                }
0242:                if (isNewTranslator(ot)) {
0243:                    _container.setDirtyInSystemTransaction(this );
0244:                }
0245:                installCustomFieldMetadata(ocb, new TranslatedFieldMetadata(
0246:                        this , ot));
0247:                return true;
0248:            }
0249:
0250:            private void installCustomFieldMetadata(ObjectContainerBase ocb,
0251:                    FieldMetadata customFieldMetadata) {
0252:                int fieldCount = 1;
0253:
0254:                boolean versions = generateVersionNumbers()
0255:                        && !ancestorHasVersionField();
0256:                boolean uuids = generateUUIDs() && !ancestorHasUUIDField();
0257:
0258:                if (versions) {
0259:                    fieldCount = 2;
0260:                }
0261:
0262:                if (uuids) {
0263:                    fieldCount = 3;
0264:                }
0265:
0266:                i_fields = new FieldMetadata[fieldCount];
0267:
0268:                i_fields[0] = customFieldMetadata;
0269:
0270:                // Some explanation on the thoughts here:
0271:
0272:                // Since i_fields for the translator are generated every time,
0273:                // we want to make sure that the order of fields is consistent.
0274:
0275:                // Therefore it's easier to implement with fixed index places in
0276:                // the i_fields array:
0277:
0278:                // [0] is the translator
0279:                // [1] is the version
0280:                // [2] is the UUID
0281:
0282:                if (versions || uuids) {
0283:
0284:                    // We don't want to have a null field, so let's add the version
0285:                    // number, if we have a UUID, even if it's not needed.
0286:
0287:                    i_fields[1] = ocb.versionIndex();
0288:                }
0289:
0290:                if (uuids) {
0291:                    i_fields[2] = ocb.uUIDIndex();
0292:                }
0293:
0294:                setStateOK();
0295:            }
0296:
0297:            private ObjectTranslator getTranslator() {
0298:                return i_config == null ? null : i_config.getTranslator();
0299:            }
0300:
0301:            private boolean isNewTranslator(ObjectTranslator ot) {
0302:                return !hasFields()
0303:                        || !ot.getClass().getName().equals(
0304:                                i_fields[0].getName());
0305:            }
0306:
0307:            private boolean hasFields() {
0308:                return i_fields != null && i_fields.length > 0;
0309:            }
0310:
0311:            void addToIndex(LocalObjectContainer a_stream, Transaction a_trans,
0312:                    int a_id) {
0313:                if (a_stream.maintainsIndices()) {
0314:                    addToIndex1(a_stream, a_trans, a_id);
0315:                }
0316:            }
0317:
0318:            void addToIndex1(LocalObjectContainer a_stream,
0319:                    Transaction a_trans, int a_id) {
0320:                if (i_ancestor != null) {
0321:                    i_ancestor.addToIndex1(a_stream, a_trans, a_id);
0322:                }
0323:                if (hasClassIndex()) {
0324:                    _index.add(a_trans, a_id);
0325:                }
0326:            }
0327:
0328:            boolean allowsQueries() {
0329:                return hasClassIndex();
0330:            }
0331:
0332:            public void cascadeActivation(Transaction a_trans, Object a_object,
0333:                    int a_depth, boolean a_activate) {
0334:                Config4Class config = configOrAncestorConfig();
0335:                if (config != null) {
0336:                    if (a_activate) {
0337:                        a_depth = config.adjustActivationDepth(a_depth);
0338:                    }
0339:                }
0340:                if (a_depth > 0) {
0341:                    ObjectContainerBase stream = a_trans.container();
0342:                    if (a_activate) {
0343:                        if (isValueType()) {
0344:                            activateFields(a_trans, a_object, a_depth - 1);
0345:                        } else {
0346:                            stream.stillToActivate(a_trans, a_object,
0347:                                    a_depth - 1);
0348:                        }
0349:                    } else {
0350:                        stream.stillToDeactivate(a_trans, a_object,
0351:                                a_depth - 1, false);
0352:                    }
0353:                }
0354:            }
0355:
0356:            void checkChanges() {
0357:                if (stateOK()) {
0358:                    if (!bitIsTrue(Const4.CHECKED_CHANGES)) {
0359:                        bitTrue(Const4.CHECKED_CHANGES);
0360:                        if (i_ancestor != null) {
0361:                            i_ancestor.checkChanges();
0362:                            // Ancestor first, so the object length calculates
0363:                            // correctly
0364:                        }
0365:                        if (_reflector != null) {
0366:                            addMembers(_container);
0367:                            if (!_container.isClient()) {
0368:                                write(_container.systemTransaction());
0369:                            }
0370:                        }
0371:                    }
0372:                }
0373:            }
0374:
0375:            public void checkType() {
0376:                ReflectClass claxx = classReflector();
0377:                if (claxx == null) {
0378:                    return;
0379:                }
0380:                if (_container._handlers.ICLASS_INTERNAL
0381:                        .isAssignableFrom(claxx)) {
0382:                    _internal = true;
0383:                }
0384:                if (_container._handlers.ICLASS_UNVERSIONED
0385:                        .isAssignableFrom(claxx)) {
0386:                    _unversioned = true;
0387:                }
0388:                if (_container._handlers.ICLASS_DB4OTYPEIMPL
0389:                        .isAssignableFrom(claxx)) {
0390:                    Db4oTypeImpl db4oTypeImpl = (Db4oTypeImpl) claxx
0391:                            .newInstance();
0392:                    _classIndexed = (db4oTypeImpl == null || db4oTypeImpl
0393:                            .hasClassIndex());
0394:                } else if (i_config != null) {
0395:                    _classIndexed = i_config.indexed();
0396:                }
0397:            }
0398:
0399:            public final int adjustUpdateDepth(Transaction trans, int depth) {
0400:                Config4Class config = configOrAncestorConfig();
0401:                if (depth == Const4.UNSPECIFIED) {
0402:                    depth = checkUpdateDepthUnspecified(trans.container()
0403:                            .configImpl());
0404:                    if (classReflector().isCollection()) {
0405:                        depth = adjustDepthToBorders(depth);
0406:                    }
0407:                }
0408:                if (config == null) {
0409:                    return depth - 1;
0410:                }
0411:                boolean cascadeOnDelete = config.cascadeOnDelete() == TernaryBool.YES;
0412:                boolean cascadeOnUpdate = config.cascadeOnUpdate() == TernaryBool.YES;
0413:
0414:                if (cascadeOnDelete || cascadeOnUpdate) {
0415:                    depth = adjustDepthToBorders(depth);
0416:                }
0417:                return depth - 1;
0418:            }
0419:
0420:            private int adjustDepthToBorders(int depth) {
0421:                int depthBorder = reflector().collectionUpdateDepth(
0422:                        classReflector());
0423:                if (depth > Integer.MIN_VALUE && depth < depthBorder) {
0424:                    depth = depthBorder;
0425:                }
0426:                return depth;
0427:            }
0428:
0429:            private final int checkUpdateDepthUnspecified(Config4Impl config) {
0430:                int depth = config.updateDepth() + 1;
0431:                if (i_config != null && i_config.updateDepth() != 0) {
0432:                    depth = i_config.updateDepth() + 1;
0433:                }
0434:                if (i_ancestor != null) {
0435:                    int ancestordepth = i_ancestor
0436:                            .checkUpdateDepthUnspecified(config);
0437:                    if (ancestordepth > depth) {
0438:                        return ancestordepth;
0439:                    }
0440:                }
0441:                return depth;
0442:            }
0443:
0444:            public void collectConstraints(Transaction a_trans,
0445:                    QConObject a_parent, Object a_object, Visitor4 a_visitor) {
0446:                if (i_fields != null) {
0447:                    for (int i = 0; i < i_fields.length; i++) {
0448:                        i_fields[i].collectConstraints(a_trans, a_parent,
0449:                                a_object, a_visitor);
0450:                    }
0451:                }
0452:                if (i_ancestor != null) {
0453:                    i_ancestor.collectConstraints(a_trans, a_parent, a_object,
0454:                            a_visitor);
0455:                }
0456:            }
0457:
0458:            public final TreeInt collectFieldIDs(MarshallerFamily mf,
0459:                    ObjectHeaderAttributes attributes, TreeInt tree,
0460:                    StatefulBuffer a_bytes, String name) {
0461:                return mf._object.collectFieldIDs(tree, this , attributes,
0462:                        a_bytes, name);
0463:            }
0464:
0465:            public boolean customizedNewInstance() {
0466:                return configInstantiates();
0467:            }
0468:
0469:            public Config4Class config() {
0470:                return i_config;
0471:            }
0472:
0473:            public Config4Class configOrAncestorConfig() {
0474:                if (i_config != null) {
0475:                    return i_config;
0476:                }
0477:                if (i_ancestor != null) {
0478:                    return i_ancestor.configOrAncestorConfig();
0479:                }
0480:                return null;
0481:            }
0482:
0483:            private boolean createConstructor(ObjectContainerBase container,
0484:                    String className) {
0485:                ReflectClass claxx = container.reflector().forName(className);
0486:                return createConstructor(container, claxx, className, true);
0487:            }
0488:
0489:            public boolean createConstructor(ObjectContainerBase a_stream,
0490:                    ReflectClass a_class, String a_name, boolean errMessages) {
0491:
0492:                _reflector = a_class;
0493:
0494:                _eventDispatcher = EventDispatcher.forClass(a_stream, a_class);
0495:
0496:                if (!Deploy.csharp) {
0497:                    if (a_class != null) {
0498:                        _isEnum = Platform4.jdk().isEnum(reflector(), a_class);
0499:                    }
0500:                }
0501:
0502:                if (customizedNewInstance()) {
0503:                    return true;
0504:                }
0505:
0506:                if (a_class != null) {
0507:                    if (a_stream._handlers.ICLASS_TRANSIENTCLASS
0508:                            .isAssignableFrom(a_class)
0509:                            || Platform4.isTransient(a_class)) {
0510:                        a_class = null;
0511:                    }
0512:                }
0513:                if (a_class == null) {
0514:                    if (a_name == null || !Platform4.isDb4oClass(a_name)) {
0515:                        if (errMessages) {
0516:                            a_stream.logMsg(23, a_name);
0517:                        }
0518:                    }
0519:                    setStateDead();
0520:                    return false;
0521:                }
0522:
0523:                if (a_stream._handlers.createConstructor(a_class,
0524:                        !callConstructor())) {
0525:                    return true;
0526:                }
0527:
0528:                setStateDead();
0529:                if (errMessages) {
0530:                    a_stream.logMsg(7, a_name);
0531:                }
0532:
0533:                if (a_stream.configImpl().exceptionsOnNotStorable()) {
0534:                    throw new ObjectNotStorableException(a_class);
0535:                }
0536:
0537:                return false;
0538:
0539:            }
0540:
0541:            public void deactivate(Transaction trans, Object obj, int depth) {
0542:                if (objectCanDeactivate(trans, obj)) {
0543:                    deactivate1(trans, obj, depth);
0544:                    objectOnDeactivate(trans, obj);
0545:                }
0546:            }
0547:
0548:            private void objectOnDeactivate(Transaction transaction, Object obj) {
0549:                ObjectContainerBase container = transaction.container();
0550:                container.callbacks().objectOnDeactivate(transaction, obj);
0551:                dispatchEvent(container, obj, EventDispatcher.DEACTIVATE);
0552:            }
0553:
0554:            private boolean objectCanDeactivate(Transaction transaction,
0555:                    Object obj) {
0556:                ObjectContainerBase container = transaction.container();
0557:                return container.callbacks().objectCanDeactivate(transaction,
0558:                        obj)
0559:                        && dispatchEvent(container, obj,
0560:                                EventDispatcher.CAN_DEACTIVATE);
0561:            }
0562:
0563:            void deactivate1(Transaction a_trans, Object a_object, int a_depth) {
0564:
0565:                for (int i = 0; i < i_fields.length; i++) {
0566:                    i_fields[i].deactivate(a_trans, a_object, a_depth);
0567:                }
0568:                if (i_ancestor != null) {
0569:                    i_ancestor.deactivate1(a_trans, a_object, a_depth);
0570:                }
0571:            }
0572:
0573:            final void delete(StatefulBuffer a_bytes, Object a_object) {
0574:                ObjectHeader oh = new ObjectHeader(_container, this , a_bytes);
0575:                delete1(oh._marshallerFamily, oh._headerAttributes, a_bytes,
0576:                        a_object);
0577:            }
0578:
0579:            private final void delete1(MarshallerFamily mf,
0580:                    ObjectHeaderAttributes attributes, StatefulBuffer a_bytes,
0581:                    Object a_object) {
0582:                removeFromIndex(a_bytes.getTransaction(), a_bytes.getID());
0583:                deleteMembers(mf, attributes, a_bytes, a_bytes.getTransaction()
0584:                        .container()._handlers.arrayType(a_object), false);
0585:            }
0586:
0587:            public void deleteEmbedded(MarshallerFamily mf,
0588:                    StatefulBuffer a_bytes) throws Db4oIOException {
0589:                if (a_bytes.cascadeDeletes() > 0) {
0590:                    int id = a_bytes.readInt();
0591:                    if (id > 0) {
0592:                        deleteEmbedded1(mf, a_bytes, id);
0593:                    }
0594:                } else {
0595:                    a_bytes.incrementOffset(linkLength());
0596:                }
0597:            }
0598:
0599:            /** @param mf */
0600:            public void deleteEmbedded1(MarshallerFamily mf,
0601:                    StatefulBuffer a_bytes, int a_id) throws Db4oIOException {
0602:                if (a_bytes.cascadeDeletes() > 0) {
0603:
0604:                    ObjectContainerBase stream = a_bytes.getStream();
0605:
0606:                    // short-term reference to prevent WeakReference-gc to hit
0607:                    Transaction transaction = a_bytes.getTransaction();
0608:                    Object obj = stream.getByID2(transaction, a_id);
0609:
0610:                    int cascade = a_bytes.cascadeDeletes() - 1;
0611:                    if (obj != null) {
0612:                        if (isCollection(obj)) {
0613:                            cascade += reflector().collectionUpdateDepth(
0614:                                    reflector().forObject(obj)) - 1;
0615:                        }
0616:                    }
0617:
0618:                    ObjectReference yo = transaction.referenceForId(a_id);
0619:                    if (yo != null) {
0620:                        a_bytes.getStream().delete2(transaction, yo, obj,
0621:                                cascade, false);
0622:                    }
0623:                }
0624:            }
0625:
0626:            void deleteMembers(MarshallerFamily mf,
0627:                    ObjectHeaderAttributes attributes, StatefulBuffer a_bytes,
0628:                    int a_type, boolean isUpdate) {
0629:                try {
0630:                    Config4Class config = configOrAncestorConfig();
0631:                    if (config != null
0632:                            && (config.cascadeOnDelete() == TernaryBool.YES)) {
0633:                        int preserveCascade = a_bytes.cascadeDeletes();
0634:                        if (classReflector().isCollection()) {
0635:                            int newCascade = preserveCascade
0636:                                    + reflector().collectionUpdateDepth(
0637:                                            classReflector()) - 3;
0638:                            if (newCascade < 1) {
0639:                                newCascade = 1;
0640:                            }
0641:                            a_bytes.setCascadeDeletes(newCascade);
0642:                        } else {
0643:                            a_bytes.setCascadeDeletes(1);
0644:                        }
0645:                        mf._object.deleteMembers(this , attributes, a_bytes,
0646:                                a_type, isUpdate);
0647:                        a_bytes.setCascadeDeletes(preserveCascade);
0648:                    } else {
0649:                        mf._object.deleteMembers(this , attributes, a_bytes,
0650:                                a_type, isUpdate);
0651:                    }
0652:                } catch (Exception e) {
0653:
0654:                    // This a catch for changed class hierarchies.
0655:                    // It's quite ugly to catch all here but it does
0656:                    // help to heal migration from earlier db4o
0657:                    // versions.
0658:
0659:                    if (Debug.atHome) {
0660:                        e.printStackTrace();
0661:                    }
0662:                }
0663:            }
0664:
0665:            public final boolean dispatchEvent(ObjectContainerBase stream,
0666:                    Object obj, int message) {
0667:                if (!dispatchingEvents(stream)) {
0668:                    return true;
0669:                }
0670:                return _eventDispatcher.dispatch(stream, obj, message);
0671:            }
0672:
0673:            private boolean dispatchingEvents(ObjectContainerBase stream) {
0674:                return _eventDispatcher != null && stream.dispatchsEvents();
0675:            }
0676:
0677:            public boolean hasEventRegistered(ObjectContainerBase stream,
0678:                    int eventID) {
0679:                if (!dispatchingEvents(stream)) {
0680:                    return true;
0681:                }
0682:                return _eventDispatcher.hasEventRegistered(eventID);
0683:            }
0684:
0685:            public final int fieldCount() {
0686:                int count = i_fields.length;
0687:
0688:                if (i_ancestor != null) {
0689:                    count += i_ancestor.fieldCount();
0690:                }
0691:
0692:                return count;
0693:            }
0694:
0695:            private static class FieldMetadataIterator implements  Iterator4 {
0696:                private final ClassMetadata _initialClazz;
0697:                private ClassMetadata _curClazz;
0698:                private int _curIdx;
0699:
0700:                public FieldMetadataIterator(ClassMetadata clazz) {
0701:                    _initialClazz = clazz;
0702:                    reset();
0703:                }
0704:
0705:                public Object current() {
0706:                    return _curClazz.i_fields[_curIdx];
0707:                }
0708:
0709:                public boolean moveNext() {
0710:                    if (_curClazz == null) {
0711:                        _curClazz = _initialClazz;
0712:                        _curIdx = 0;
0713:                    } else {
0714:                        _curIdx++;
0715:                    }
0716:                    while (_curClazz != null && !indexInRange()) {
0717:                        _curClazz = _curClazz.i_ancestor;
0718:                        _curIdx = 0;
0719:                    }
0720:                    return _curClazz != null && indexInRange();
0721:                }
0722:
0723:                public void reset() {
0724:                    _curClazz = null;
0725:                    _curIdx = -1;
0726:                }
0727:
0728:                private boolean indexInRange() {
0729:                    return _curIdx < _curClazz.i_fields.length;
0730:                }
0731:            }
0732:
0733:            public Iterator4 fields() {
0734:                return new FieldMetadataIterator(this );
0735:            }
0736:
0737:            // Scrolls offset in passed reader to the offset the passed field should
0738:            // be read at.
0739:            public final HandlerVersion findOffset(Buffer buffer,
0740:                    FieldMetadata field) {
0741:                if (buffer == null) {
0742:                    return HandlerVersion.INVALID;
0743:                }
0744:                buffer._offset = 0;
0745:                ObjectHeader oh = new ObjectHeader(_container, this , buffer);
0746:                boolean res = oh.objectMarshaller().findOffset(this ,
0747:                        oh._headerAttributes, buffer, field);
0748:                if (!res) {
0749:                    return HandlerVersion.INVALID;
0750:                }
0751:                return new HandlerVersion(oh.handlerVersion());
0752:            }
0753:
0754:            void forEachFieldMetadata(Visitor4 visitor) {
0755:                if (i_fields != null) {
0756:                    for (int i = 0; i < i_fields.length; i++) {
0757:                        visitor.visit(i_fields[i]);
0758:                    }
0759:                }
0760:                if (i_ancestor != null) {
0761:                    i_ancestor.forEachFieldMetadata(visitor);
0762:                }
0763:            }
0764:
0765:            public static ClassMetadata forObject(Transaction trans,
0766:                    Object obj, boolean allowCreation) {
0767:                ReflectClass reflectClass = trans.reflector().forObject(obj);
0768:
0769:                // TODO: The following conditions look strange. Check !
0770:                if (reflectClass != null
0771:                        && reflectClass.getSuperclass() == null && obj != null) {
0772:                    throw new ObjectNotStorableException(obj.toString());
0773:                }
0774:
0775:                if (allowCreation) {
0776:                    return trans.container().produceClassMetadata(reflectClass);
0777:                }
0778:                return trans.container().classMetadataForReflectClass(
0779:                        reflectClass);
0780:            }
0781:
0782:            public boolean generateUUIDs() {
0783:                if (!generateVirtual()) {
0784:                    return false;
0785:                }
0786:                boolean configValue = (i_config == null) ? false : i_config
0787:                        .generateUUIDs();
0788:                return generate1(_container.config().generateUUIDs(),
0789:                        configValue);
0790:            }
0791:
0792:            private boolean generateVersionNumbers() {
0793:                if (!generateVirtual()) {
0794:                    return false;
0795:                }
0796:                boolean configValue = (i_config == null) ? false : i_config
0797:                        .generateVersionNumbers();
0798:                return generate1(_container.config().generateVersionNumbers(),
0799:                        configValue);
0800:            }
0801:
0802:            private boolean generateVirtual() {
0803:                if (_unversioned) {
0804:                    return false;
0805:                }
0806:                if (_internal) {
0807:                    return false;
0808:                }
0809:                return true;
0810:            }
0811:
0812:            private boolean generate1(ConfigScope globalConfig,
0813:                    boolean individualConfig) {
0814:                return globalConfig.applyConfig(individualConfig);
0815:            }
0816:
0817:            ClassMetadata getAncestor() {
0818:                return i_ancestor;
0819:            }
0820:
0821:            public Object getComparableObject(Object forObject) {
0822:                if (i_config != null) {
0823:                    if (i_config.queryAttributeProvider() != null) {
0824:                        return i_config.queryAttributeProvider().attribute(
0825:                                forObject);
0826:                    }
0827:                }
0828:                return forObject;
0829:            }
0830:
0831:            public ClassMetadata getHigherHierarchy(ClassMetadata a_yapClass) {
0832:                ClassMetadata yc = getHigherHierarchy1(a_yapClass);
0833:                if (yc != null) {
0834:                    return yc;
0835:                }
0836:                return a_yapClass.getHigherHierarchy1(this );
0837:            }
0838:
0839:            private ClassMetadata getHigherHierarchy1(ClassMetadata a_yapClass) {
0840:                if (a_yapClass == this ) {
0841:                    return this ;
0842:                }
0843:                if (i_ancestor != null) {
0844:                    return i_ancestor.getHigherHierarchy1(a_yapClass);
0845:                }
0846:                return null;
0847:            }
0848:
0849:            public ClassMetadata getHigherOrCommonHierarchy(
0850:                    ClassMetadata a_yapClass) {
0851:                ClassMetadata yc = getHigherHierarchy1(a_yapClass);
0852:                if (yc != null) {
0853:                    return yc;
0854:                }
0855:                if (i_ancestor != null) {
0856:                    yc = i_ancestor.getHigherOrCommonHierarchy(a_yapClass);
0857:                    if (yc != null) {
0858:                        return yc;
0859:                    }
0860:                }
0861:                return a_yapClass.getHigherHierarchy1(this );
0862:            }
0863:
0864:            public byte getIdentifier() {
0865:                return Const4.YAPCLASS;
0866:            }
0867:
0868:            public long[] getIDs() {
0869:                synchronized (lock()) {
0870:                    if (!stateOK()) {
0871:                        return new long[0];
0872:                    }
0873:                    return getIDs(_container.transaction());
0874:                }
0875:            }
0876:
0877:            public long[] getIDs(Transaction trans) {
0878:                synchronized (lock()) {
0879:                    if (!stateOK()) {
0880:                        return new long[0];
0881:                    }
0882:                    if (!hasClassIndex()) {
0883:                        return new long[0];
0884:                    }
0885:                    return trans.container().getIDsForClass(trans, this );
0886:                }
0887:            }
0888:
0889:            public boolean hasClassIndex() {
0890:                return _classIndexed;
0891:            }
0892:
0893:            private boolean ancestorHasUUIDField() {
0894:                if (i_ancestor == null) {
0895:                    return false;
0896:                }
0897:                return i_ancestor.hasUUIDField();
0898:            }
0899:
0900:            private boolean hasUUIDField() {
0901:                if (ancestorHasUUIDField()) {
0902:                    return true;
0903:                }
0904:                return Arrays4.containsInstanceOf(i_fields,
0905:                        UUIDFieldMetadata.class);
0906:            }
0907:
0908:            private boolean ancestorHasVersionField() {
0909:                if (i_ancestor == null) {
0910:                    return false;
0911:                }
0912:                return i_ancestor.hasVersionField();
0913:            }
0914:
0915:            private boolean hasVersionField() {
0916:                if (ancestorHasVersionField()) {
0917:                    return true;
0918:                }
0919:                return Arrays4.containsInstanceOf(i_fields,
0920:                        VersionFieldMetadata.class);
0921:            }
0922:
0923:            public ClassIndexStrategy index() {
0924:                return _index;
0925:            }
0926:
0927:            public int indexEntryCount(Transaction ta) {
0928:                if (!stateOK()) {
0929:                    return 0;
0930:                }
0931:                return _index.entryCount(ta);
0932:            }
0933:
0934:            public Object indexEntryToObject(Transaction trans,
0935:                    Object indexEntry) {
0936:                if (indexEntry == null) {
0937:                    return null;
0938:                }
0939:                int id = ((Integer) indexEntry).intValue();
0940:                return container().getByID2(trans, id);
0941:            }
0942:
0943:            public ReflectClass classReflector() {
0944:                return _reflector;
0945:            }
0946:
0947:            public String getName() {
0948:                if (i_name == null) {
0949:                    if (_reflector != null) {
0950:                        i_name = _reflector.getName();
0951:                    }
0952:                }
0953:                return i_name;
0954:            }
0955:
0956:            public StoredClass getParentStoredClass() {
0957:                return getAncestor();
0958:            }
0959:
0960:            public StoredField[] getStoredFields() {
0961:                synchronized (lock()) {
0962:                    if (i_fields == null) {
0963:                        return new StoredField[0];
0964:                    }
0965:                    StoredField[] fields = new StoredField[i_fields.length];
0966:                    System.arraycopy(i_fields, 0, fields, 0, i_fields.length);
0967:                    return fields;
0968:                }
0969:            }
0970:
0971:            final ObjectContainerBase container() {
0972:                return _container;
0973:            }
0974:
0975:            public FieldMetadata fieldMetadataForName(final String name) {
0976:                final FieldMetadata[] yf = new FieldMetadata[1];
0977:                forEachFieldMetadata(new Visitor4() {
0978:                    public void visit(Object obj) {
0979:                        if (name.equals(((FieldMetadata) obj).getName())) {
0980:                            yf[0] = (FieldMetadata) obj;
0981:                        }
0982:                    }
0983:                });
0984:                return yf[0];
0985:
0986:            }
0987:
0988:            /** @param container */
0989:            public boolean hasField(ObjectContainerBase container,
0990:                    String fieldName) {
0991:                if (classReflector().isCollection()) {
0992:                    return true;
0993:                }
0994:                return fieldMetadataForName(fieldName) != null;
0995:            }
0996:
0997:            boolean hasVirtualAttributes() {
0998:                if (_internal) {
0999:                    return false;
1000:                }
1001:                return hasVersionField() || hasUUIDField();
1002:            }
1003:
1004:            public boolean holdsAnyClass() {
1005:                return classReflector().isCollection();
1006:            }
1007:
1008:            void incrementFieldsOffset1(Buffer a_bytes) {
1009:                int length = readFieldCount(a_bytes);
1010:                for (int i = 0; i < length; i++) {
1011:                    i_fields[i].incrementOffset(a_bytes);
1012:                }
1013:            }
1014:
1015:            final boolean init(ObjectContainerBase a_stream,
1016:                    ClassMetadata a_ancestor, ReflectClass claxx) {
1017:
1018:                if (DTrace.enabled) {
1019:                    DTrace.YAPCLASS_INIT.log(getID());
1020:                }
1021:
1022:                setAncestor(a_ancestor);
1023:
1024:                Config4Impl config = a_stream.configImpl();
1025:                String className = claxx.getName();
1026:                setConfig(config.configClass(className));
1027:
1028:                if (!createConstructor(a_stream, claxx, className, false)) {
1029:                    return false;
1030:                }
1031:
1032:                checkType();
1033:                if (allowsQueries()) {
1034:                    _index.initialize(a_stream);
1035:                }
1036:                i_name = className;
1037:                i_ancestor = a_ancestor;
1038:                bitTrue(Const4.CHECKED_CHANGES);
1039:
1040:                return true;
1041:            }
1042:
1043:            final void initConfigOnUp(Transaction systemTrans) {
1044:                Config4Class extendedConfig = Platform4.extendConfiguration(
1045:                        _reflector, _container.configure(), i_config);
1046:                if (extendedConfig != null) {
1047:                    i_config = extendedConfig;
1048:                }
1049:                if (i_config == null) {
1050:                    return;
1051:                }
1052:                if (!stateOK()) {
1053:                    return;
1054:                }
1055:
1056:                if (i_fields == null) {
1057:                    return;
1058:                }
1059:
1060:                for (int i = 0; i < i_fields.length; i++) {
1061:                    FieldMetadata curField = i_fields[i];
1062:                    String fieldName = curField.getName();
1063:                    if (!curField.hasConfig() && extendedConfig != null
1064:                            && extendedConfig.configField(fieldName) != null) {
1065:                        curField.initIndex(this , fieldName);
1066:                    }
1067:                    curField.initConfigOnUp(systemTrans);
1068:                }
1069:            }
1070:
1071:            void initOnUp(Transaction systemTrans) {
1072:                if (!stateOK()) {
1073:                    return;
1074:                }
1075:                initConfigOnUp(systemTrans);
1076:                storeStaticFieldValues(systemTrans, false);
1077:            }
1078:
1079:            public Object instantiate(UnmarshallingContext context) {
1080:
1081:                // overridden in YapClassPrimitive
1082:                // never called for primitive YapAny
1083:
1084:                context.adjustInstantiationDepth();
1085:
1086:                Object obj = context.persistentObject();
1087:
1088:                final boolean instantiating = (obj == null);
1089:                if (instantiating) {
1090:                    obj = instantiateObject(context);
1091:                    if (obj == null) {
1092:                        return null;
1093:                    }
1094:
1095:                    shareTransaction(obj, context.transaction());
1096:                    shareObjectReference(obj, context.reference());
1097:
1098:                    context.setObjectWeak(obj);
1099:
1100:                    context.transaction().referenceSystem()
1101:                            .addExistingReferenceToObjectTree(
1102:                                    context.reference());
1103:
1104:                    objectOnInstantiate(context.transaction(), obj);
1105:                }
1106:
1107:                context.addToIDTree();
1108:
1109:                if (instantiating) {
1110:                    if (context.activationDepth() == 0) {
1111:                        context.reference().setStateDeactivated();
1112:                    } else {
1113:                        activate(context);
1114:                    }
1115:                } else {
1116:                    if (activatingActiveObject(context.container(), context
1117:                            .reference())) {
1118:                        if (context.activationDepth() > 1) {
1119:                            activateFields(context.transaction(), obj, context
1120:                                    .activationDepth() - 1);
1121:                        }
1122:                    } else {
1123:                        activate(context);
1124:                    }
1125:                }
1126:                return obj;
1127:            }
1128:
1129:            public Object instantiateTransient(UnmarshallingContext context) {
1130:
1131:                // overridden in YapClassPrimitive
1132:                // never called for primitive YapAny
1133:
1134:                Object obj = instantiateObject(context);
1135:                if (obj == null) {
1136:                    return null;
1137:                }
1138:                context.container().peeked(context.objectID(), obj);
1139:                instantiateFields(context);
1140:                return obj;
1141:
1142:            }
1143:
1144:            private boolean activatingActiveObject(
1145:                    final ObjectContainerBase container, ObjectReference ref) {
1146:                return !container._refreshInsteadOfActivate && ref.isActive();
1147:            }
1148:
1149:            private void activate(UnmarshallingContext context) {
1150:                if (!objectCanActivate(context.transaction(), context
1151:                        .persistentObject())) {
1152:                    context.reference().setStateDeactivated();
1153:                    return;
1154:                }
1155:                context.reference().setStateClean();
1156:                if (context.activationDepth() > 0 || cascadeOnActivate()) {
1157:                    instantiateFields(context);
1158:                }
1159:                objectOnActivate(context.transaction(), context
1160:                        .persistentObject());
1161:            }
1162:
1163:            private boolean configInstantiates() {
1164:                return config() != null && config().instantiates();
1165:            }
1166:
1167:            private Object instantiateObject(UnmarshallingContext context) {
1168:                Object obj = configInstantiates() ? instantiateFromConfig(context)
1169:                        : instantiateFromReflector(context.container());
1170:                context.persistentObject(obj);
1171:                return obj;
1172:            }
1173:
1174:            private void objectOnInstantiate(Transaction transaction,
1175:                    Object instance) {
1176:                transaction.container().callbacks().objectOnInstantiate(
1177:                        transaction, instance);
1178:            }
1179:
1180:            Object instantiateFromReflector(ObjectContainerBase stream) {
1181:                if (_reflector == null) {
1182:                    return null;
1183:                }
1184:
1185:                stream.instantiating(true);
1186:                try {
1187:                    return _reflector.newInstance();
1188:                } catch (NoSuchMethodError e) {
1189:                    stream.logMsg(7, classReflector().getName());
1190:                    return null;
1191:                } catch (Exception e) {
1192:                    // TODO: be more helpful here
1193:                    return null;
1194:                } finally {
1195:                    stream.instantiating(false);
1196:                }
1197:            }
1198:
1199:            private Object instantiateFromConfig(UnmarshallingContext context) {
1200:
1201:                int offset = context.offset();
1202:
1203:                // Field length is always 1
1204:                context.seek(offset + Const4.INT_LENGTH);
1205:
1206:                try {
1207:                    return i_config.instantiate(context.container(),
1208:                            i_fields[0].read(context));
1209:                } finally {
1210:                    context.seek(offset);
1211:                }
1212:            }
1213:
1214:            private boolean cascadeOnActivate() {
1215:                return i_config != null
1216:                        && (i_config.cascadeOnActivate() == TernaryBool.YES);
1217:            }
1218:
1219:            private void shareObjectReference(Object obj, ObjectReference ref) {
1220:                if (obj instanceof  Db4oTypeImpl) {
1221:                    ((Db4oTypeImpl) obj).setObjectReference(ref);
1222:                }
1223:            }
1224:
1225:            private void shareTransaction(Object obj, Transaction transaction) {
1226:                if (obj instanceof  TransactionAware) {
1227:                    ((TransactionAware) obj).setTrans(transaction);
1228:                }
1229:            }
1230:
1231:            private void objectOnActivate(Transaction transaction, Object obj) {
1232:                ObjectContainerBase container = transaction.container();
1233:                container.callbacks().objectOnActivate(transaction, obj);
1234:                dispatchEvent(container, obj, EventDispatcher.ACTIVATE);
1235:            }
1236:
1237:            private boolean objectCanActivate(Transaction transaction,
1238:                    Object obj) {
1239:                ObjectContainerBase container = transaction.container();
1240:                return container.callbacks()
1241:                        .objectCanActivate(transaction, obj)
1242:                        && dispatchEvent(container, obj,
1243:                                EventDispatcher.CAN_ACTIVATE);
1244:            }
1245:
1246:            void instantiateFields(UnmarshallingContext context) {
1247:                MarshallerFamily.version(context.handlerVersion())._object
1248:                        .instantiateFields(context);
1249:            }
1250:
1251:            public boolean isArray() {
1252:                return classReflector().isCollection();
1253:            }
1254:
1255:            boolean isCollection(Object obj) {
1256:                return reflector().forObject(obj).isCollection();
1257:            }
1258:
1259:            public boolean isDirty() {
1260:                if (!stateOK()) {
1261:                    return false;
1262:                }
1263:                return super .isDirty();
1264:            }
1265:
1266:            boolean isEnum() {
1267:                return _isEnum;
1268:            }
1269:
1270:            public boolean isPrimitive() {
1271:                return false;
1272:            }
1273:
1274:            /**
1275:             * no any, primitive, array or other tricks. overriden in YapClassAny and
1276:             * YapClassPrimitive
1277:             */
1278:            public boolean isStrongTyped() {
1279:                return true;
1280:            }
1281:
1282:            public boolean isValueType() {
1283:                return Platform4.isValueType(classReflector());
1284:            }
1285:
1286:            private final Object lock() {
1287:                return _container.lock();
1288:            }
1289:
1290:            public String nameToWrite() {
1291:                if (i_config != null && i_config.writeAs() != null) {
1292:                    return i_config.writeAs();
1293:                }
1294:                if (i_name == null) {
1295:                    return "";
1296:                }
1297:                return _container.configImpl().resolveAliasRuntimeName(i_name);
1298:            }
1299:
1300:            public final boolean callConstructor() {
1301:                TernaryBool specialized = callConstructorSpecialized();
1302:                // FIXME: If specified, return yes?!?
1303:                if (!specialized.unspecified()) {
1304:                    return specialized.definiteYes();
1305:                }
1306:                return _container.configImpl().callConstructors().definiteYes();
1307:            }
1308:
1309:            private final TernaryBool callConstructorSpecialized() {
1310:                if (i_config != null) {
1311:                    TernaryBool res = i_config.callConstructor();
1312:                    if (!res.unspecified()) {
1313:                        return res;
1314:                    }
1315:                }
1316:                if (_isEnum) {
1317:                    return TernaryBool.NO;
1318:                }
1319:                if (i_ancestor != null) {
1320:                    return i_ancestor.callConstructorSpecialized();
1321:                }
1322:                return TernaryBool.UNSPECIFIED;
1323:            }
1324:
1325:            public int ownLength() {
1326:                return MarshallerFamily.current()._class.marshalledLength(
1327:                        _container, this );
1328:            }
1329:
1330:            void purge() {
1331:                _index.purge();
1332:
1333:                // TODO: may want to add manual purge to Btree
1334:                //       indexes here
1335:            }
1336:
1337:            public Object readValueType(Transaction trans, int id, int depth) {
1338:                // for C# value types only:
1339:                // they need to be instantiated fully before setting them
1340:                // on the parent object because the set call modifies identity.
1341:
1342:                // We also have to instantiate structs completely every time.
1343:                int newDepth = Math.max(1, depth);
1344:
1345:                // TODO: Do we want value types in the ID tree?
1346:                // Shouldn't we treat them like strings and update
1347:                // them every time ???		
1348:                ObjectReference ref = trans.referenceForId(id);
1349:                if (ref != null) {
1350:                    Object obj = ref.getObject();
1351:                    if (obj == null) {
1352:                        trans.removeReference(ref);
1353:                    } else {
1354:                        ref.activate(trans, obj, newDepth, false);
1355:                        return ref.getObject();
1356:                    }
1357:                }
1358:                return new ObjectReference(id).read(trans, newDepth,
1359:                        Const4.ADD_TO_ID_TREE, false);
1360:            }
1361:
1362:            public TypeHandler4 readArrayHandler(Transaction a_trans,
1363:                    MarshallerFamily mf, Buffer[] a_bytes) {
1364:                if (isArray()) {
1365:                    return this ;
1366:                }
1367:                return null;
1368:            }
1369:
1370:            public TypeHandler4 readArrayHandler1(Buffer[] a_bytes) {
1371:                if (DTrace.enabled) {
1372:                    if (a_bytes[0] instanceof  StatefulBuffer) {
1373:                        DTrace.READ_ARRAY_WRAPPER
1374:                                .log(((StatefulBuffer) a_bytes[0]).getID());
1375:                    }
1376:                }
1377:                if (isArray()) {
1378:                    if (Platform4.isCollectionTranslator(this .i_config)) {
1379:                        a_bytes[0].incrementOffset(Const4.INT_LENGTH);
1380:                        return new ArrayHandler(_container, null, false);
1381:                    }
1382:                    incrementFieldsOffset1(a_bytes[0]);
1383:                    if (i_ancestor != null) {
1384:                        return i_ancestor.readArrayHandler1(a_bytes);
1385:                    }
1386:                }
1387:                return null;
1388:            }
1389:
1390:            public ObjectID readObjectID(InternalReadContext context) {
1391:                int id = context.readInt();
1392:                return id == 0 ? ObjectID.IS_NULL : new ObjectID(id);
1393:            }
1394:
1395:            public void readCandidates(int handlerVersion, final Buffer buffer,
1396:                    final QCandidates candidates) {
1397:                int id = 0;
1398:
1399:                int offset = buffer._offset;
1400:                try {
1401:                    id = buffer.readInt();
1402:                } catch (Exception e) {
1403:                }
1404:                buffer._offset = offset;
1405:
1406:                if (id != 0) {
1407:                    final Transaction trans = candidates.i_trans;
1408:                    Object obj = trans.container().getByID(trans, id);
1409:                    if (obj != null) {
1410:
1411:                        candidates.i_trans.container().activate(trans, obj, 2);
1412:                        Platform4.forEachCollectionElement(obj, new Visitor4() {
1413:                            public void visit(Object elem) {
1414:                                candidates.addByIdentity(new QCandidate(
1415:                                        candidates, elem, trans.container()
1416:                                                .getID(trans, elem), true));
1417:                            }
1418:                        });
1419:                    }
1420:
1421:                }
1422:            }
1423:
1424:            public final int readFieldCount(Buffer buffer) {
1425:                int count = buffer.readInt();
1426:                if (count > i_fields.length) {
1427:                    if (Debug.atHome) {
1428:                        System.out.println("ClassMetadata.readFieldCount "
1429:                                + getName() + " count to high:" + count
1430:                                + " i_fields:" + i_fields.length);
1431:                        new Exception().printStackTrace();
1432:                    }
1433:                    return i_fields.length;
1434:                }
1435:                return count;
1436:            }
1437:
1438:            public Object readIndexEntry(Buffer a_reader) {
1439:                return new Integer(a_reader.readInt());
1440:            }
1441:
1442:            public Object readIndexEntry(MarshallerFamily mf,
1443:                    StatefulBuffer a_writer) throws CorruptionException {
1444:                return readIndexEntry(a_writer);
1445:            }
1446:
1447:            byte[] readName(Transaction a_trans) {
1448:                i_reader = a_trans.container().readReaderByID(a_trans, getID());
1449:                return readName1(a_trans, i_reader);
1450:            }
1451:
1452:            public final byte[] readName1(Transaction trans, Buffer reader) {
1453:                if (reader == null)
1454:                    return null;
1455:
1456:                i_reader = reader;
1457:                boolean ok = false;
1458:                try {
1459:                    ClassMarshaller marshaller = MarshallerFamily.current()._class;
1460:                    i_nameBytes = marshaller.readName(trans, reader);
1461:                    _metaClassID = marshaller.readMetaClassID(reader);
1462:
1463:                    setStateUnread();
1464:
1465:                    bitFalse(Const4.CHECKED_CHANGES);
1466:                    bitFalse(Const4.STATIC_FIELDS_STORED);
1467:
1468:                    ok = true;
1469:                    return i_nameBytes;
1470:
1471:                } finally {
1472:                    if (!ok) {
1473:                        setStateDead();
1474:                    }
1475:                }
1476:            }
1477:
1478:            void readVirtualAttributes(Transaction a_trans,
1479:                    ObjectReference a_yapObject) {
1480:                int id = a_yapObject.getID();
1481:                ObjectContainerBase stream = a_trans.container();
1482:                Buffer reader = stream.readReaderByID(a_trans, id);
1483:                ObjectHeader oh = new ObjectHeader(stream, this , reader);
1484:                oh.objectMarshaller().readVirtualAttributes(a_trans, this ,
1485:                        a_yapObject, oh._headerAttributes, reader);
1486:            }
1487:
1488:            GenericReflector reflector() {
1489:                return _container.reflector();
1490:            }
1491:
1492:            public void rename(String newName) {
1493:                if (!_container.isClient()) {
1494:                    int tempState = _state;
1495:                    setStateOK();
1496:                    i_name = newName;
1497:                    setStateDirty();
1498:                    write(_container.systemTransaction());
1499:                    _state = tempState;
1500:                } else {
1501:                    Exceptions4.throwRuntimeException(58);
1502:                }
1503:            }
1504:
1505:            final void createConfigAndConstructor(Hashtable4 a_byteHashTable,
1506:                    ReflectClass claxx, String name) {
1507:                i_name = name;
1508:                setConfig(_container.configImpl().configClass(i_name));
1509:                if (claxx == null) {
1510:                    createConstructor(_container, i_name);
1511:                } else {
1512:                    createConstructor(_container, claxx, i_name, true);
1513:                }
1514:                if (i_nameBytes != null) {
1515:                    a_byteHashTable.remove(i_nameBytes);
1516:                    i_nameBytes = null;
1517:                }
1518:            }
1519:
1520:            String resolveName(ReflectClass claxx) {
1521:                if (claxx != null) {
1522:                    return claxx.getName();
1523:                }
1524:                if (i_nameBytes != null) {
1525:                    String name = _container.stringIO().read(i_nameBytes);
1526:                    return _container.configImpl().resolveAliasStoredName(name);
1527:                }
1528:                throw new IllegalStateException();
1529:            }
1530:
1531:            boolean readThis() {
1532:                if (stateUnread()) {
1533:                    setStateOK();
1534:                    setStateClean();
1535:                    forceRead();
1536:                    return true;
1537:                }
1538:                return false;
1539:            }
1540:
1541:            final void forceRead() {
1542:                if (i_reader == null || bitIsTrue(Const4.READING)) {
1543:                    return;
1544:                }
1545:
1546:                bitTrue(Const4.READING);
1547:
1548:                MarshallerFamily.forConverterVersion(_container
1549:                        .converterVersion())._class.read(_container, this ,
1550:                        i_reader);
1551:
1552:                i_nameBytes = null;
1553:                i_reader = null;
1554:                bitFalse(Const4.READING);
1555:            }
1556:
1557:            public void readThis(Transaction a_trans, Buffer a_reader) {
1558:                throw Exceptions4.virtualException();
1559:            }
1560:
1561:            public void refresh() {
1562:                if (!stateUnread()) {
1563:                    createConstructor(_container, i_name);
1564:                    bitFalse(Const4.CHECKED_CHANGES);
1565:                    checkChanges();
1566:                    if (i_fields != null) {
1567:                        for (int i = 0; i < i_fields.length; i++) {
1568:                            i_fields[i].refresh();
1569:                        }
1570:                    }
1571:                }
1572:            }
1573:
1574:            void removeFromIndex(Transaction ta, int id) {
1575:                if (hasClassIndex()) {
1576:                    _index.remove(ta, id);
1577:                }
1578:                if (i_ancestor != null) {
1579:                    i_ancestor.removeFromIndex(ta, id);
1580:                }
1581:            }
1582:
1583:            boolean renameField(String a_from, String a_to) {
1584:                boolean renamed = false;
1585:                for (int i = 0; i < i_fields.length; i++) {
1586:                    if (i_fields[i].getName().equals(a_to)) {
1587:                        _container.logMsg(9, "class:" + getName() + " field:"
1588:                                + a_to);
1589:                        return false;
1590:                    }
1591:                }
1592:                for (int i = 0; i < i_fields.length; i++) {
1593:                    if (i_fields[i].getName().equals(a_from)) {
1594:                        i_fields[i].setName(a_to);
1595:                        renamed = true;
1596:                    }
1597:                }
1598:                return renamed;
1599:            }
1600:
1601:            void setConfig(Config4Class config) {
1602:
1603:                if (config == null) {
1604:                    return;
1605:                }
1606:
1607:                // The configuration can be set by a ObjectClass#readAs setting
1608:                // from YapClassCollection, right after reading the meta information
1609:                // for the first time. In that case we never change the setting
1610:                if (i_config == null) {
1611:                    i_config = config;
1612:                }
1613:            }
1614:
1615:            void setName(String a_name) {
1616:                i_name = a_name;
1617:            }
1618:
1619:            final void setStateDead() {
1620:                bitTrue(Const4.DEAD);
1621:                bitFalse(Const4.CONTINUE);
1622:            }
1623:
1624:            private final void setStateUnread() {
1625:                bitFalse(Const4.DEAD);
1626:                bitTrue(Const4.CONTINUE);
1627:            }
1628:
1629:            private final void setStateOK() {
1630:                bitFalse(Const4.DEAD);
1631:                bitFalse(Const4.CONTINUE);
1632:            }
1633:
1634:            boolean stateDead() {
1635:                return bitIsTrue(Const4.DEAD);
1636:            }
1637:
1638:            private final boolean stateOK() {
1639:                return bitIsFalse(Const4.CONTINUE) && bitIsFalse(Const4.DEAD)
1640:                        && bitIsFalse(Const4.READING);
1641:            }
1642:
1643:            final boolean stateOKAndAncestors() {
1644:                if (!stateOK() || i_fields == null) {
1645:                    return false;
1646:                }
1647:                if (i_ancestor != null) {
1648:                    return i_ancestor.stateOKAndAncestors();
1649:                }
1650:                return true;
1651:            }
1652:
1653:            boolean stateUnread() {
1654:                return bitIsTrue(Const4.CONTINUE) && bitIsFalse(Const4.DEAD)
1655:                        && bitIsFalse(Const4.READING);
1656:            }
1657:
1658:            boolean storeField(ReflectField a_field) {
1659:                if (a_field.isStatic()) {
1660:                    return false;
1661:                }
1662:                if (a_field.isTransient()) {
1663:                    Config4Class config = configOrAncestorConfig();
1664:                    if (config == null) {
1665:                        return false;
1666:                    }
1667:                    if (!config.storeTransientFields()) {
1668:                        return false;
1669:                    }
1670:                }
1671:                return Platform4.canSetAccessible() || a_field.isPublic();
1672:            }
1673:
1674:            public StoredField storedField(String name, Object clazz) {
1675:                synchronized (lock()) {
1676:
1677:                    ClassMetadata classMetadata = _container
1678:                            .classMetadataForReflectClass(ReflectorUtils
1679:                                    .reflectClassFor(reflector(), clazz));
1680:
1681:                    if (i_fields != null) {
1682:                        for (int i = 0; i < i_fields.length; i++) {
1683:                            if (i_fields[i].getName().equals(name)) {
1684:
1685:                                // FIXME: The == comparison in the following line could be wrong. 
1686:
1687:                                if (classMetadata == null
1688:                                        || classMetadata == i_fields[i]
1689:                                                .handlerClassMetadata(_container)) {
1690:                                    return (i_fields[i]);
1691:                                }
1692:                            }
1693:                        }
1694:                    }
1695:
1696:                    //TODO: implement field creation
1697:
1698:                    return null;
1699:                }
1700:            }
1701:
1702:            void storeStaticFieldValues(Transaction trans, boolean force) {
1703:                if (bitIsTrue(Const4.STATIC_FIELDS_STORED) && !force) {
1704:                    return;
1705:                }
1706:                bitTrue(Const4.STATIC_FIELDS_STORED);
1707:
1708:                if (!shouldStoreStaticFields(trans)) {
1709:                    return;
1710:                }
1711:
1712:                final ObjectContainerBase stream = trans.container();
1713:                stream.showInternalClasses(true);
1714:                try {
1715:                    StaticClass sc = queryStaticClass(trans);
1716:                    if (sc == null) {
1717:                        createStaticClass(trans);
1718:                    } else {
1719:                        updateStaticClass(trans, sc);
1720:                    }
1721:                } finally {
1722:                    stream.showInternalClasses(false);
1723:                }
1724:            }
1725:
1726:            private boolean shouldStoreStaticFields(Transaction trans) {
1727:                return !trans.container().config().isReadOnly()
1728:                        && (staticFieldValuesArePersisted() || Platform4
1729:                                .storeStaticFieldValues(trans.reflector(),
1730:                                        classReflector()));
1731:            }
1732:
1733:            private void updateStaticClass(final Transaction trans,
1734:                    final StaticClass sc) {
1735:                final ObjectContainerBase stream = trans.container();
1736:                stream.activate(trans, sc, 4);
1737:
1738:                final StaticField[] existingFields = sc.fields;
1739:                final Iterator4 staticFields = Iterators.map(
1740:                        staticReflectFields(), new Function4() {
1741:                            public Object apply(Object arg) {
1742:                                final ReflectField reflectField = (ReflectField) arg;
1743:                                StaticField existingField = fieldByName(
1744:                                        existingFields, reflectField.getName());
1745:                                if (existingField != null) {
1746:                                    updateExistingStaticField(trans,
1747:                                            existingField, reflectField);
1748:                                    return existingField;
1749:                                }
1750:                                return toStaticField(reflectField);
1751:                            }
1752:                        });
1753:                sc.fields = toStaticFieldArray(staticFields);
1754:                if (!stream.isClient()) {
1755:                    setStaticClass(trans, sc);
1756:                }
1757:            }
1758:
1759:            private void createStaticClass(Transaction trans) {
1760:                if (trans.container().isClient()) {
1761:                    return;
1762:                }
1763:                StaticClass sc = new StaticClass(i_name,
1764:                        toStaticFieldArray(staticReflectFieldsToStaticFields()));
1765:                setStaticClass(trans, sc);
1766:            }
1767:
1768:            private Iterator4 staticReflectFieldsToStaticFields() {
1769:                return Iterators.map(staticReflectFields(), new Function4() {
1770:                    public Object apply(Object arg) {
1771:                        return toStaticField((ReflectField) arg);
1772:                    }
1773:                });
1774:            }
1775:
1776:            protected StaticField toStaticField(final ReflectField reflectField) {
1777:                return new StaticField(reflectField.getName(),
1778:                        staticReflectFieldValue(reflectField));
1779:            }
1780:
1781:            private Object staticReflectFieldValue(
1782:                    final ReflectField reflectField) {
1783:                reflectField.setAccessible();
1784:                return reflectField.get(null);
1785:            }
1786:
1787:            private void setStaticClass(Transaction trans, StaticClass sc) {
1788:                // TODO: we should probably use a specific update depth here, 4?
1789:                trans.container().setInternal(trans, sc, true);
1790:            }
1791:
1792:            private StaticField[] toStaticFieldArray(Iterator4 iterator4) {
1793:                return toStaticFieldArray(new Collection4(iterator4));
1794:            }
1795:
1796:            private StaticField[] toStaticFieldArray(Collection4 fields) {
1797:                return (StaticField[]) fields.toArray(new StaticField[fields
1798:                        .size()]);
1799:            }
1800:
1801:            private Iterator4 staticReflectFields() {
1802:                return Iterators.filter(reflectFields(), new Predicate4() {
1803:                    public boolean match(Object candidate) {
1804:                        return ((ReflectField) candidate).isStatic();
1805:                    }
1806:                });
1807:            }
1808:
1809:            private ReflectField[] reflectFields() {
1810:                return classReflector().getDeclaredFields();
1811:            }
1812:
1813:            protected void updateExistingStaticField(Transaction trans,
1814:                    StaticField existingField, final ReflectField reflectField) {
1815:                final ObjectContainerBase stream = trans.container();
1816:                final Object newValue = staticReflectFieldValue(reflectField);
1817:
1818:                if (existingField.value != null
1819:                        && newValue != null
1820:                        && existingField.value.getClass() == newValue
1821:                                .getClass()) {
1822:                    int id = stream.getID(trans, existingField.value);
1823:                    if (id > 0) {
1824:                        if (existingField.value != newValue) {
1825:
1826:                            // This is the clue:
1827:                            // Bind the current static member to it's old database identity,
1828:                            // so constants and enums will work with '=='
1829:                            stream.bind(trans, newValue, id);
1830:
1831:                            // This may produce unwanted side effects if the static field object
1832:                            // was modified in the current session. TODO:Add documentation case.
1833:
1834:                            stream.refresh(trans, newValue, Integer.MAX_VALUE);
1835:
1836:                            existingField.value = newValue;
1837:                        }
1838:                        return;
1839:                    }
1840:                }
1841:
1842:                if (newValue == null) {
1843:                    try {
1844:                        reflectField.set(null, existingField.value);
1845:                    } catch (Exception ex) {
1846:                        // fail silently
1847:                        // TODO: why?
1848:                    }
1849:                    return;
1850:                }
1851:
1852:                existingField.value = newValue;
1853:            }
1854:
1855:            private boolean staticFieldValuesArePersisted() {
1856:                return (i_config != null && i_config
1857:                        .staticFieldValuesArePersisted());
1858:            }
1859:
1860:            protected StaticField fieldByName(StaticField[] fields,
1861:                    final String fieldName) {
1862:                for (int i = 0; i < fields.length; i++) {
1863:                    final StaticField field = fields[i];
1864:                    if (fieldName.equals(field.name)) {
1865:                        return field;
1866:                    }
1867:                }
1868:                return null;
1869:            }
1870:
1871:            private StaticClass queryStaticClass(Transaction trans) {
1872:                Query q = trans.container().query(trans);
1873:                q.constrain(Const4.CLASS_STATICCLASS);
1874:                q.descend("name").constrain(i_name);
1875:                ObjectSet os = q.execute();
1876:                return os.size() > 0 ? (StaticClass) os.next() : null;
1877:            }
1878:
1879:            public String toString() {
1880:                if (i_name != null) {
1881:                    return i_name;
1882:                }
1883:                if (i_nameBytes == null) {
1884:                    return "*CLASS NAME UNKNOWN*";
1885:                }
1886:                LatinStringIO stringIO = _container == null ? Const4.stringIO
1887:                        : _container.stringIO();
1888:                return stringIO.read(i_nameBytes);
1889:            }
1890:
1891:            public boolean writeObjectBegin() {
1892:                if (!stateOK()) {
1893:                    return false;
1894:                }
1895:                return super .writeObjectBegin();
1896:            }
1897:
1898:            public void writeIndexEntry(Buffer a_writer, Object a_object) {
1899:
1900:                if (a_object == null) {
1901:                    a_writer.writeInt(0);
1902:                    return;
1903:                }
1904:
1905:                a_writer.writeInt(((Integer) a_object).intValue());
1906:            }
1907:
1908:            public final void writeThis(Transaction trans, Buffer writer) {
1909:                MarshallerFamily.current()._class.write(trans, this , writer);
1910:            }
1911:
1912:            // Comparison_______________________
1913:
1914:            private ReflectClass i_compareTo;
1915:
1916:            public Comparable4 prepareComparison(Object obj) {
1917:                if (obj == null) {
1918:                    i_lastID = 0;
1919:                    i_compareTo = null;
1920:                    return this ;
1921:                }
1922:                if (obj instanceof  Integer) {
1923:                    i_lastID = ((Integer) obj).intValue();
1924:                } else if (obj instanceof  TransactionContext) {
1925:                    TransactionContext tc = (TransactionContext) obj;
1926:                    obj = tc._object;
1927:                    i_lastID = _container.getID(tc._transaction, obj);
1928:                } else {
1929:                    throw new IllegalComparisonException();
1930:                }
1931:                i_compareTo = reflector().forObject(obj);
1932:                return this ;
1933:            }
1934:
1935:            public int compareTo(Object obj) {
1936:                if (obj instanceof  TransactionContext) {
1937:                    obj = ((TransactionContext) obj)._object;
1938:                }
1939:                if (obj instanceof  Integer) {
1940:                    return ((Integer) obj).intValue() - i_lastID;
1941:                }
1942:                if (obj == null) {
1943:                    if (i_compareTo == null) {
1944:                        return 0;
1945:                    }
1946:                    return -1;
1947:                }
1948:                if (i_compareTo != null) {
1949:                    if (i_compareTo
1950:                            .isAssignableFrom(reflector().forObject(obj))) {
1951:                        return 0;
1952:                    }
1953:                }
1954:                throw new IllegalComparisonException();
1955:            }
1956:
1957:            public static void defragObject(BufferPair readers) {
1958:                ObjectHeader header = ObjectHeader.defrag(readers);
1959:                header._marshallerFamily._object.defragFields(header
1960:                        .classMetadata(), header, readers);
1961:                if (Deploy.debug) {
1962:                    readers.readEnd();
1963:                }
1964:            }
1965:
1966:            public void defrag(MarshallerFamily mf, BufferPair readers,
1967:                    boolean redirect) {
1968:                if (hasClassIndex()) {
1969:                    readers.copyID();
1970:                } else {
1971:                    readers.copyUnindexedID();
1972:                }
1973:                int restLength = (linkLength() - Const4.INT_LENGTH);
1974:                readers.incrementOffset(restLength);
1975:            }
1976:
1977:            public void defragClass(BufferPair readers, int classIndexID)
1978:                    throws CorruptionException, IOException {
1979:                MarshallerFamily mf = MarshallerFamily.current();
1980:                mf._class.defrag(this , _container.stringIO(), readers,
1981:                        classIndexID);
1982:            }
1983:
1984:            public static ClassMetadata readClass(ObjectContainerBase stream,
1985:                    Buffer reader) {
1986:                ObjectHeader oh = new ObjectHeader(stream, reader);
1987:                return oh.classMetadata();
1988:            }
1989:
1990:            public boolean isAssignableFrom(ClassMetadata other) {
1991:                return classReflector()
1992:                        .isAssignableFrom(other.classReflector());
1993:            }
1994:
1995:            public final void defragIndexEntry(BufferPair readers) {
1996:                readers.copyID();
1997:            }
1998:
1999:            public void setAncestor(ClassMetadata ancestor) {
2000:                if (ancestor == this ) {
2001:                    throw new IllegalStateException();
2002:                }
2003:                i_ancestor = ancestor;
2004:            }
2005:
2006:            public Object wrapWithTransactionContext(Transaction transaction,
2007:                    Object value) {
2008:                if (value instanceof  Integer) {
2009:                    return value;
2010:                }
2011:                return new TransactionContext(transaction, value);
2012:            }
2013:
2014:            public Object read(ReadContext context) {
2015:
2016:                // FIXME: .NET value types should get their own TypeHandler and it 
2017:                //        should do the following:
2018:                if (isValueType()) {
2019:                    return readValueType(context.transaction(), context
2020:                            .readInt(), ((UnmarshallingContext) context)
2021:                            .activationDepth() - 1);
2022:                }
2023:
2024:                return context.readObject();
2025:            }
2026:
2027:            public void write(WriteContext context, Object obj) {
2028:                context.writeObject(obj);
2029:            }
2030:
2031:            public TypeHandler4 typeHandler() {
2032:                return this;
2033:            }
2034:
2035:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.