1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002,2008 Oracle. All rights reserved. 5 * 6 * $Id: SimpleCatalog.java,v 1.1 2008/02/07 17:12:27 mark Exp $ 7 */ 8 9package com.sleepycat.persist.impl; 10 11import java.util.ArrayList; 12import java.util.HashMap; 13import java.util.IdentityHashMap; 14import java.util.List; 15import java.util.Map; 16import java.util.NoSuchElementException; 17 18import com.sleepycat.persist.model.EntityModel; 19import com.sleepycat.persist.raw.RawObject; 20 21/** 22 * A static catalog containing simple types only. Once created, this catalog 23 * is immutable. 24 * 25 * For bindings accessed by a PersistComparator during recovery, the 26 * SimpleCatalog provides formats for all simple types. To reduce redundant 27 * format objects, the SimpleCatalog's formats are copied when creating a 28 * regular PersistCatalog. 29 * 30 * This class also contains utility methods for dealing with primitives. 31 * 32 * @author Mark Hayes 33 */ 34public class SimpleCatalog implements Catalog { 35 36 private static final Map<String,Class> keywordToPrimitive; 37 static { 38 keywordToPrimitive = new HashMap<String,Class>(8); 39 keywordToPrimitive.put("boolean", Boolean.TYPE); 40 keywordToPrimitive.put("char", Character.TYPE); 41 keywordToPrimitive.put("byte", Byte.TYPE); 42 keywordToPrimitive.put("short", Short.TYPE); 43 keywordToPrimitive.put("int", Integer.TYPE); 44 keywordToPrimitive.put("long", Long.TYPE); 45 keywordToPrimitive.put("float", Float.TYPE); 46 keywordToPrimitive.put("double", Double.TYPE); 47 } 48 49 private static final Map<Class,Class> primitiveTypeToWrapper; 50 static { 51 primitiveTypeToWrapper = new HashMap<Class,Class>(8); 52 primitiveTypeToWrapper.put(Boolean.TYPE, Boolean.class); 53 primitiveTypeToWrapper.put(Character.TYPE, Character.class); 54 primitiveTypeToWrapper.put(Byte.TYPE, Byte.class); 55 primitiveTypeToWrapper.put(Short.TYPE, Short.class); 56 primitiveTypeToWrapper.put(Integer.TYPE, Integer.class); 57 primitiveTypeToWrapper.put(Long.TYPE, Long.class); 58 primitiveTypeToWrapper.put(Float.TYPE, Float.class); 59 primitiveTypeToWrapper.put(Double.TYPE, Double.class); 60 } 61 62 private static final SimpleCatalog instance = new SimpleCatalog(); 63 64 static SimpleCatalog getInstance() { 65 return instance; 66 } 67 68 static boolean isSimpleType(Class type) { 69 return instance.formatMap.containsKey(type.getName()); 70 } 71 72 static Class primitiveToWrapper(Class type) { 73 Class cls = primitiveTypeToWrapper.get(type); 74 if (cls == null) { 75 throw new IllegalStateException(type.getName()); 76 } 77 return cls; 78 } 79 80 public static Class keyClassForName(String className) { 81 Class cls = keywordToPrimitive.get(className); 82 if (cls != null) { 83 cls = primitiveTypeToWrapper.get(cls); 84 } else { 85 try { 86 cls = EntityModel.classForName(className); 87 } catch (ClassNotFoundException e) { 88 throw new IllegalArgumentException 89 ("Key class not found: " + className); 90 } 91 } 92 return cls; 93 } 94 95 public static String keyClassName(String className) { 96 Class cls = keywordToPrimitive.get(className); 97 if (cls != null) { 98 cls = primitiveTypeToWrapper.get(cls); 99 return cls.getName(); 100 } else { 101 return className; 102 } 103 } 104 105 public static Class classForName(String className) 106 throws ClassNotFoundException { 107 108 Class cls = keywordToPrimitive.get(className); 109 if (cls == null) { 110 cls = EntityModel.classForName(className); 111 } 112 return cls; 113 } 114 115 static SimpleFormat getSimpleFormat(Class type) { 116 return instance.formatMap.get(type.getName()); 117 } 118 119 static List<Format> copyFormatList() { 120 return new ArrayList<Format>(instance.formatList); 121 } 122 123 static boolean copyMissingFormats(List<Format> copyToList) { 124 boolean anyCopied = false; 125 for (int i = 0; i <= Format.ID_PREDEFINED; i += 1) { 126 Format thisFormat = instance.formatList.get(i); 127 Format otherFormat = copyToList.get(i); 128 if (thisFormat != null && otherFormat == null) { 129 copyToList.set(i, thisFormat); 130 anyCopied = true; 131 } 132 } 133 return anyCopied; 134 } 135 136 private List<SimpleFormat> formatList; 137 private Map<String,SimpleFormat> formatMap; 138 139 private SimpleCatalog() { 140 141 /* 142 * Reserve slots for all predefined IDs, so that that next ID assigned 143 * will be Format.ID_PREDEFINED plus one. 144 */ 145 int initCapacity = Format.ID_PREDEFINED * 2; 146 formatList = new ArrayList<SimpleFormat>(initCapacity); 147 formatMap = new HashMap<String,SimpleFormat>(initCapacity); 148 149 for (int i = 0; i <= Format.ID_PREDEFINED; i += 1) { 150 formatList.add(null); 151 } 152 153 /* Initialize all predefined formats. */ 154 setFormat(Format.ID_BOOL, new SimpleFormat.FBool(true)); 155 setFormat(Format.ID_BOOL_W, new SimpleFormat.FBool(false)); 156 setFormat(Format.ID_BYTE, new SimpleFormat.FByte(true)); 157 setFormat(Format.ID_BYTE_W, new SimpleFormat.FByte(false)); 158 setFormat(Format.ID_SHORT, new SimpleFormat.FShort(true)); 159 setFormat(Format.ID_SHORT_W, new SimpleFormat.FShort(false)); 160 setFormat(Format.ID_INT, new SimpleFormat.FInt(true)); 161 setFormat(Format.ID_INT_W, new SimpleFormat.FInt(false)); 162 setFormat(Format.ID_LONG, new SimpleFormat.FLong(true)); 163 setFormat(Format.ID_LONG_W, new SimpleFormat.FLong(false)); 164 setFormat(Format.ID_FLOAT, new SimpleFormat.FFloat(true)); 165 setFormat(Format.ID_FLOAT_W, new SimpleFormat.FFloat(false)); 166 setFormat(Format.ID_DOUBLE, new SimpleFormat.FDouble(true)); 167 setFormat(Format.ID_DOUBLE_W, new SimpleFormat.FDouble(false)); 168 setFormat(Format.ID_CHAR, new SimpleFormat.FChar(true)); 169 setFormat(Format.ID_CHAR_W, new SimpleFormat.FChar(false)); 170 setFormat(Format.ID_STRING, new SimpleFormat.FString()); 171 setFormat(Format.ID_BIGINT, new SimpleFormat.FBigInt()); 172 /* 173 setFormat(Format.ID_BIGDEC, new SimpleFormat.FBigDec()); 174 */ 175 setFormat(Format.ID_DATE, new SimpleFormat.FDate()); 176 177 /* Tell primitives about their wrapper class. */ 178 setWrapper(Format.ID_BOOL, Format.ID_BOOL_W); 179 setWrapper(Format.ID_BYTE, Format.ID_BYTE_W); 180 setWrapper(Format.ID_SHORT, Format.ID_SHORT_W); 181 setWrapper(Format.ID_INT, Format.ID_INT_W); 182 setWrapper(Format.ID_LONG, Format.ID_LONG_W); 183 setWrapper(Format.ID_FLOAT, Format.ID_FLOAT_W); 184 setWrapper(Format.ID_DOUBLE, Format.ID_DOUBLE_W); 185 setWrapper(Format.ID_CHAR, Format.ID_CHAR_W); 186 } 187 188 /** 189 * Sets a format for which space in the formatList has been preallocated, 190 * and makes it the current format for the class. 191 */ 192 private void setFormat(int id, SimpleFormat format) { 193 format.setId(id); 194 format.initializeIfNeeded(this); 195 formatList.set(id, format); 196 formatMap.put(format.getClassName(), format); 197 } 198 199 /** 200 * Tells a primitive format about the format for its corresponding 201 * primitive wrapper class. 202 */ 203 private void setWrapper(int primitiveId, int wrapperId) { 204 SimpleFormat primitiveFormat = formatList.get(primitiveId); 205 SimpleFormat wrapperFormat = formatList.get(wrapperId); 206 primitiveFormat.setWrapperFormat(wrapperFormat); 207 } 208 209 public int getInitVersion(Format format, boolean forReader) { 210 return Catalog.CURRENT_VERSION; 211 } 212 213 public Format getFormat(int formatId) { 214 Format format; 215 try { 216 format = formatList.get(formatId); 217 if (format == null) { 218 throw new IllegalStateException 219 ("Not a simple type: " + formatId); 220 } 221 return format; 222 } catch (NoSuchElementException e) { 223 throw new IllegalStateException 224 ("Not a simple type: " + formatId); 225 } 226 } 227 228 public Format getFormat(Class cls) { 229 Format format = formatMap.get(cls.getName()); 230 if (format == null) { 231 throw new IllegalArgumentException 232 ("Not a simple type: " + cls.getName()); 233 } 234 return format; 235 } 236 237 public Format getFormat(String className) { 238 return formatMap.get(className); 239 } 240 241 public Format createFormat(String clsName, Map<String,Format> newFormats) { 242 throw new IllegalStateException(); 243 } 244 245 public Format createFormat(Class type, Map<String,Format> newFormats) { 246 throw new IllegalStateException(); 247 } 248 249 public boolean isRawAccess() { 250 return false; 251 } 252 253 public Object convertRawObject(RawObject o, IdentityHashMap converted) { 254 throw new IllegalStateException(); 255 } 256} 257