001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: EnhancedAccessor.java,v 1.11.2.3 2008/01/07 15:14:19 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.impl;
010:
011: import java.lang.reflect.Array;
012: import java.lang.reflect.Modifier;
013: import java.util.Collections;
014: import java.util.HashMap;
015: import java.util.Map;
016:
017: /**
018: * Implements Accessor for a complex persistent class.
019: *
020: * @author Mark Hayes
021: */
022: public class EnhancedAccessor implements Accessor {
023:
024: private static final Map<String, Enhanced> classRegistry = Collections
025: .synchronizedMap(new HashMap<String, Enhanced>());
026:
027: /* Is public for unit tests. */
028: public static final boolean EXPECT_ENHANCED = "true".equals(System
029: .getProperty("expectEnhanced"));
030:
031: private Enhanced prototype;
032: private Format priKeyFormat;
033: private Class type;
034:
035: /**
036: * Registers a prototype instance, and should be called during
037: * initialization of the prototype class. The prototype may be null for
038: * an abstract class.
039: */
040: public static void registerClass(String className,
041: Enhanced prototype) {
042: classRegistry.put(className, prototype);
043: }
044:
045: /**
046: * Returns whether a given class is a (registered) enhanced class.
047: */
048: static boolean isEnhanced(Class type) {
049: boolean enhanced = classRegistry.containsKey(type.getName());
050: if (!enhanced && EXPECT_ENHANCED) {
051: throw new IllegalStateException(
052: "Test was run with expectEnhanced=true but class "
053: + type.getName() + " is not enhanced");
054: }
055: return enhanced;
056: }
057:
058: /**
059: * Creates an accessor.
060: */
061: EnhancedAccessor(Class type) {
062: this .type = type;
063: prototype = classRegistry.get(type.getName());
064: assert prototype != null
065: || Modifier.isAbstract(type.getModifiers());
066: }
067:
068: /**
069: * Creates an accessor for a complex type.
070: */
071: EnhancedAccessor(Catalog catalog, Class type, ComplexFormat format) {
072: this (type);
073:
074: /*
075: * Find the primary key format for this format or one of its superclass
076: * formats.
077: */
078: ComplexFormat declaringFormat = format;
079: while (declaringFormat != null) {
080: String priKeyField = declaringFormat.getPriKeyField();
081: if (priKeyField != null) {
082: Class declaringType = declaringFormat.getType();
083: Class fieldType;
084: try {
085: fieldType = declaringType.getDeclaredField(
086: priKeyField).getType();
087: } catch (NoSuchFieldException e) {
088: throw new IllegalStateException(e);
089: }
090: priKeyFormat = catalog.getFormat(fieldType);
091: break;
092: } else {
093: Format super Format = declaringFormat.getSuperFormat();
094: declaringFormat = (ComplexFormat) super Format;
095: }
096: }
097: }
098:
099: public Object newInstance() {
100: if (prototype == null) {
101: /* Abstract class -- internal error. */
102: throw new IllegalStateException();
103: }
104: return prototype.bdbNewInstance();
105: }
106:
107: public Object newArray(int len) {
108: if (prototype == null) {
109: /* Abstract class -- use reflection for now. */
110: return Array.newInstance(type, len);
111: }
112: return prototype.bdbNewArray(len);
113: }
114:
115: public boolean isPriKeyFieldNullOrZero(Object o) {
116: if (priKeyFormat == null) {
117: throw new IllegalStateException("No primary key: "
118: + o.getClass().getName());
119: }
120: return ((Enhanced) o).bdbIsPriKeyFieldNullOrZero();
121: }
122:
123: public void writePriKeyField(Object o, EntityOutput output) {
124: if (priKeyFormat == null) {
125: throw new IllegalStateException("No primary key: "
126: + o.getClass().getName());
127: }
128: ((Enhanced) o).bdbWritePriKeyField(output, priKeyFormat);
129: }
130:
131: public void readPriKeyField(Object o, EntityInput input) {
132: if (priKeyFormat == null) {
133: throw new IllegalStateException("No primary key: "
134: + o.getClass().getName());
135: }
136: ((Enhanced) o).bdbReadPriKeyField(input, priKeyFormat);
137: }
138:
139: public void writeSecKeyFields(Object o, EntityOutput output) {
140: ((Enhanced) o).bdbWriteSecKeyFields(output);
141: }
142:
143: public void readSecKeyFields(Object o, EntityInput input,
144: int startField, int endField, int super Level) {
145: ((Enhanced) o).bdbReadSecKeyFields(input, startField, endField,
146: super Level);
147: }
148:
149: public void writeNonKeyFields(Object o, EntityOutput output) {
150: ((Enhanced) o).bdbWriteNonKeyFields(output);
151: }
152:
153: public void readNonKeyFields(Object o, EntityInput input,
154: int startField, int endField, int super Level) {
155: ((Enhanced) o).bdbReadNonKeyFields(input, startField, endField,
156: super Level);
157: }
158:
159: public Object getField(Object o, int field, int super Level,
160: boolean isSecField) {
161: return ((Enhanced) o).bdbGetField(o, field, super Level,
162: isSecField);
163: }
164:
165: public void setField(Object o, int field, int super Level,
166: boolean isSecField, Object value) {
167: ((Enhanced) o).bdbSetField(o, field, superLevel, isSecField,
168: value);
169: }
170: }
|