1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: EnhancedAccessor.java,v 1.1 2008/02/07 17:12:27 mark Exp $ 7 */ 8 9package com.sleepycat.persist.impl; 10 11import java.lang.reflect.Array; 12import java.lang.reflect.Modifier; 13import java.util.Collections; 14import java.util.HashMap; 15import java.util.Map; 16 17/** 18 * Implements Accessor for a complex persistent class. 19 * 20 * @author Mark Hayes 21 */ 22public class EnhancedAccessor implements Accessor { 23 24 private static final Map<String,Enhanced> classRegistry = 25 Collections.synchronizedMap(new HashMap<String,Enhanced>()); 26 27 /* Is public for unit tests. */ 28 public static final boolean EXPECT_ENHANCED = 29 "true".equals(System.getProperty("expectEnhanced")); 30 31 private Enhanced prototype; 32 private Format priKeyFormat; 33 private Class type; 34 35 /** 36 * Registers a prototype instance, and should be called during 37 * initialization of the prototype class. The prototype may be null for 38 * an abstract class. 39 */ 40 public static void registerClass(String className, Enhanced prototype) { 41 classRegistry.put(className, prototype); 42 } 43 44 /** 45 * Returns whether a given class is a (registered) enhanced class. 46 */ 47 static boolean isEnhanced(Class type) { 48 boolean enhanced = classRegistry.containsKey(type.getName()); 49 if (!enhanced && EXPECT_ENHANCED) { 50 throw new IllegalStateException 51 ("Test was run with expectEnhanced=true but class " + 52 type.getName() + " is not enhanced"); 53 } 54 return enhanced; 55 } 56 57 /** 58 * Creates an accessor. 59 */ 60 EnhancedAccessor(Class type) { 61 this.type = type; 62 prototype = classRegistry.get(type.getName()); 63 assert prototype != null || Modifier.isAbstract(type.getModifiers()); 64 } 65 66 /** 67 * Creates an accessor for a complex type. 68 */ 69 EnhancedAccessor(Catalog catalog, Class type, ComplexFormat format) { 70 this(type); 71 72 /* 73 * Find the primary key format for this format or one of its superclass 74 * formats. 75 */ 76 ComplexFormat declaringFormat = format; 77 while (declaringFormat != null) { 78 String priKeyField = declaringFormat.getPriKeyField(); 79 if (priKeyField != null) { 80 Class declaringType = declaringFormat.getType(); 81 Class fieldType; 82 try { 83 fieldType = 84 declaringType.getDeclaredField(priKeyField).getType(); 85 } catch (NoSuchFieldException e) { 86 throw new IllegalStateException(e); 87 } 88 priKeyFormat = catalog.getFormat(fieldType); 89 break; 90 } else { 91 Format superFormat = declaringFormat.getSuperFormat(); 92 declaringFormat = (ComplexFormat) superFormat; 93 } 94 } 95 } 96 97 public Object newInstance() { 98 if (prototype == null) { 99 /* Abstract class -- internal error. */ 100 throw new IllegalStateException(); 101 } 102 return prototype.bdbNewInstance(); 103 } 104 105 public Object newArray(int len) { 106 if (prototype == null) { 107 /* Abstract class -- use reflection for now. */ 108 return Array.newInstance(type, len); 109 } 110 return prototype.bdbNewArray(len); 111 } 112 113 public boolean isPriKeyFieldNullOrZero(Object o) { 114 if (priKeyFormat == null) { 115 throw new IllegalStateException 116 ("No primary key: " + o.getClass().getName()); 117 } 118 return ((Enhanced) o).bdbIsPriKeyFieldNullOrZero(); 119 } 120 121 public void writePriKeyField(Object o, EntityOutput output) { 122 if (priKeyFormat == null) { 123 throw new IllegalStateException 124 ("No primary key: " + o.getClass().getName()); 125 } 126 ((Enhanced) o).bdbWritePriKeyField(output, priKeyFormat); 127 } 128 129 public void readPriKeyField(Object o, EntityInput input) { 130 if (priKeyFormat == null) { 131 throw new IllegalStateException 132 ("No primary key: " + o.getClass().getName()); 133 } 134 ((Enhanced) o).bdbReadPriKeyField(input, priKeyFormat); 135 } 136 137 public void writeSecKeyFields(Object o, EntityOutput output) { 138 ((Enhanced) o).bdbWriteSecKeyFields(output); 139 } 140 141 public void readSecKeyFields(Object o, 142 EntityInput input, 143 int startField, 144 int endField, 145 int superLevel) { 146 ((Enhanced) o).bdbReadSecKeyFields 147 (input, startField, endField, superLevel); 148 } 149 150 public void writeNonKeyFields(Object o, EntityOutput output) { 151 ((Enhanced) o).bdbWriteNonKeyFields(output); 152 } 153 154 public void readNonKeyFields(Object o, 155 EntityInput input, 156 int startField, 157 int endField, 158 int superLevel) { 159 ((Enhanced) o).bdbReadNonKeyFields 160 (input, startField, endField, superLevel); 161 } 162 163 public Object getField(Object o, 164 int field, 165 int superLevel, 166 boolean isSecField) { 167 return ((Enhanced) o).bdbGetField(o, field, superLevel, isSecField); 168 } 169 170 public void setField(Object o, 171 int field, 172 int superLevel, 173 boolean isSecField, 174 Object value) { 175 ((Enhanced) o).bdbSetField(o, field, superLevel, isSecField, value); 176 } 177} 178