001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.metadata;
012:
013: import com.versant.core.util.IntObjectHashMap;
014:
015: import java.util.*;
016:
017: import com.versant.core.common.BindingSupportImpl;
018:
019: /**
020: * This maintains translation tables to translate ClassMetaData to/from
021: * String and int IDs.
022: */
023: public final class ClassIdTranslator {
024:
025: private final ModelMetaData jmd;
026: private String message;
027:
028: private final boolean stringClassIds; // are the class-id's Strings?
029:
030: private final Map cmdToIDString; // ClassMetaData -> String ID
031: private final Map idToCmdString; // String ID -> ClassMetaData
032:
033: private final Map cmdToIDInt; // ClassMetaData -> int ID
034: private final IntObjectHashMap idToCmdInt; // int ID -> ClassMetaData
035:
036: public ClassIdTranslator(ModelMetaData jmd, boolean stringClassIds,
037: Map cmdToIDString, Map idToCmdString, Map cmdToIDInt,
038: IntObjectHashMap idToCmdInt) {
039: this .jmd = jmd;
040: this .stringClassIds = stringClassIds;
041: this .cmdToIDString = cmdToIDString;
042: this .idToCmdString = idToCmdString;
043: this .cmdToIDInt = cmdToIDInt;
044: this .idToCmdInt = idToCmdInt;
045: }
046:
047: /**
048: * Set the message used to constuct exceptions for invalid classes and
049: * so on (e.g. 'field com.acme.model.Company.data').
050: */
051: public void setMessage(String message) {
052: this .message = message;
053: }
054:
055: public String getMessage() {
056: return message;
057: }
058:
059: /**
060: * Get all of the ClassMetaData's we have in alphabetical order.
061: */
062: public List getClassList() {
063: if (cmdToIDInt != null) {
064: return createArrayList(cmdToIDInt.keySet().iterator());
065: }
066: if (cmdToIDString != null) {
067: return createArrayList(cmdToIDString.keySet().iterator());
068: }
069: return Collections.EMPTY_LIST;
070: }
071:
072: private static ArrayList createArrayList(Iterator i) {
073: ArrayList a = new ArrayList();
074: for (; i.hasNext();)
075: a.add(i.next());
076: Collections.sort(a, new Comparator() {
077: public int compare(Object o1, Object o2) {
078: ClassMetaData a = (ClassMetaData) o1;
079: ClassMetaData b = (ClassMetaData) o2;
080: return a.index - b.index;
081: }
082: });
083: return a;
084: }
085:
086: /**
087: * Are the class-id's Strings (i.e. not ints)?
088: */
089: public boolean isStringClassIds() {
090: return stringClassIds;
091: }
092:
093: /**
094: * Convert an int class-id value read from our class-id column into
095: * ClassMetaData. Throws a JDODataStoreException if the classId is
096: * invalid.
097: */
098: public ClassMetaData getClassForIntClassId(int classId) {
099: ClassMetaData ans;
100: if (cmdToIDInt == null) { // use global class-id's
101: ans = jmd.getClassMetaData(classId);
102: if (ans == null) {
103: throw createUnknownClassException(Integer
104: .toString(classId));
105: }
106: } else { // use local class-id's
107: ans = (ClassMetaData) idToCmdInt.get(classId);
108: if (ans == null) {
109: ans = jmd.getClassMetaData(classId);
110: if (ans != null) { // not a valid class for this field
111: throw createInvalidClassException(ans, Integer
112: .toString(classId));
113: } else { // dodgy classId
114: throw createUnknownClassException(Integer
115: .toString(classId));
116: }
117: }
118: }
119: return ans;
120: }
121:
122: /**
123: * Convert a class into an int class-id for setting on our class-id column.
124: * Throws a JDODataStoreException if the class is invalid.
125: */
126: public int getIntClassIdForClass(ClassMetaData cmd) {
127: if (cmdToIDInt == null) {
128: return cmd.classId;
129: } else {
130: int id = ((Integer) cmdToIDInt.get(cmd)).intValue();
131: if (id < 0)
132: throw createInvalidClassException(cmd);
133: return id;
134: }
135: }
136:
137: /**
138: * Convert a String class-id value read from our class-id column into
139: * ClassMetaData. Throws a JDODataStoreException if the classId is
140: * invalid.
141: */
142: public ClassMetaData getClassForStringClassId(String classId) {
143: ClassMetaData ans = (ClassMetaData) idToCmdString.get(classId);
144: if (ans == null) {
145: throw createUnknownClassException(classId);
146: }
147: return ans;
148: }
149:
150: /**
151: * Convert a class into an String class-id for setting on our class-id
152: * column. Throws a JDODataStoreException if the class is invalid.
153: */
154: public String getStringClassIdForClass(ClassMetaData cmd) {
155: if (cmdToIDString == null) {
156: return cmd.classIdString;
157: } else {
158: String id = (String) cmdToIDString.get(cmd);
159: if (id == null)
160: throw createInvalidClassException(cmd);
161: return id;
162: }
163: }
164:
165: private RuntimeException createUnknownClassException(String classId) {
166: return BindingSupportImpl.getInstance().datastore(
167: "Unknown class-id value (" + classId + ") for "
168: + message);
169: }
170:
171: private RuntimeException createInvalidClassException(
172: ClassMetaData cmd, String classId) {
173: return BindingSupportImpl.getInstance().datastore(
174: "Instances of class " + cmd.qname + " for ID "
175: + classId + " are not allowed for " + message);
176: }
177:
178: private RuntimeException createInvalidClassException(
179: ClassMetaData cmd) {
180: return BindingSupportImpl.getInstance().datastore(
181: "Instances of class " + cmd.qname
182: + " are not allowed for " + message);
183: }
184:
185: }
|