1 2 12 package com.versant.core.jdbc; 13 14 import com.versant.core.metadata.parser.JdoExtension; 15 import com.versant.core.metadata.parser.JdoElement; 16 import com.versant.core.metadata.parser.JdoExtensionKeys; 17 import com.versant.core.metadata.MetaDataBuilder; 18 import com.versant.core.metadata.ClassMetaData; 19 import com.versant.core.metadata.ClassIdTranslator; 20 import com.versant.core.jdbc.metadata.*; 21 import com.versant.core.util.IntObjectHashMap; 22 23 import java.util.*; 24 25 import com.versant.core.common.BindingSupportImpl; 26 27 32 public class JdbcPolyRefMetaDataBuilder implements JdoExtensionKeys { 33 34 private JdbcMetaDataBuilder mdb; 35 private JdoElement context; 36 private String fieldName; 37 private JdbcField field; 38 39 private ArrayList colsList = new ArrayList(); 40 41 private JdbcColumn classIdCol; 42 private JdbcColumn[] pkCols; 43 private JdbcColumn[] cols; 44 45 private HashSet classIdSet = new HashSet(); 47 private boolean stringClassIds; 49 private Map cmdToIDString = new HashMap(); 51 private Map idToCmdString; 53 private Map cmdToIDInt = new HashMap(); 55 private IntObjectHashMap idToCmdInt; 57 private ClassIdTranslator classIdTranslator; 58 59 public JdbcPolyRefMetaDataBuilder(JdbcMetaDataBuilder mdb, 60 JdoElement context, String fieldName, JdoExtension[] extensions, 61 JdbcField field) { 62 this.mdb = mdb; 63 this.context = context; 64 this.fieldName = fieldName; 65 this.field = field; 66 process(extensions); 67 } 68 69 private void process(JdoExtension[] extensions) { 70 JdoExtension classIdColExt = null; 71 if (extensions != null) { 72 int ne = extensions.length; 73 for (int i = 0; i < ne; i++) { 74 JdoExtension e = extensions[i]; 75 switch (e.key) { 76 77 case JDBC_CLASS_ID: 78 if (classIdColExt != null) { 79 throw BindingSupportImpl.getInstance().runtime( 80 "Only one jdbc-class-id extension is allowed\n" + 81 context); 82 } 83 classIdColExt = e; 84 break; 85 86 case JDBC_REF: 87 colsList.add(mdb.createColumn(e.nested, fieldName, 88 Integer .class)); 89 break; 90 91 case VALID_CLASS: 92 processClassIdMapping(e); 93 break; 94 95 default: 96 if (e.isJdbc()) MetaDataBuilder.throwUnexpectedExtension(e); 97 break; 98 } 99 } 100 } 101 102 try { 104 for (Iterator i = cmdToIDString.keySet().iterator(); i.hasNext(); ) { 105 ClassMetaData key = (ClassMetaData)i.next(); 106 String value = (String )cmdToIDString.get(key); 107 cmdToIDInt.put(key, new Integer (value)); 108 } 109 } catch (NumberFormatException e) { 110 stringClassIds = true; 111 } 112 113 if (cmdToIDString.size() == 0) cmdToIDString = null; 115 if (cmdToIDInt.size() == 0) cmdToIDInt = null; 116 117 if (cmdToIDInt != null) { idToCmdInt = new IntObjectHashMap(); 119 for (Iterator i = cmdToIDInt.keySet().iterator(); i.hasNext(); ) { 120 ClassMetaData key = (ClassMetaData)i.next(); 121 int value = ((Integer )cmdToIDInt.get(key)).intValue(); 122 idToCmdInt.put(value, key); 123 } 124 } 125 126 if (cmdToIDString != null) { idToCmdString = new HashMap(); 128 for (Iterator i = cmdToIDString.keySet().iterator(); i.hasNext(); ) { 129 ClassMetaData key = (ClassMetaData)i.next(); 130 String value = (String )cmdToIDString.get(key); 131 idToCmdString.put(value, key); 132 } 133 } 134 135 classIdTranslator = new ClassIdTranslator(field.fmd.classMetaData.jmd, 137 stringClassIds, cmdToIDString, idToCmdString, 138 cmdToIDInt, idToCmdInt); 139 classIdTranslator.setMessage("field " + field.fmd.getQName()); 140 141 JdbcColumn[] firstPk = null; 145 List cl = classIdTranslator.getClassList(); 146 int n = cl.size(); 147 if (n > 0) { 148 ClassMetaData first = (ClassMetaData)cl.get(0); 149 firstPk = ((JdbcClass)first.storeClass).table.pk; 150 for (int i = 1; i < n; i++) { 151 ClassMetaData cmd = (ClassMetaData)cl.get(i); 152 int len = ((JdbcClass)cmd.storeClass).table.pk.length; 153 if (len != firstPk.length) { 154 throw BindingSupportImpl.getInstance().runtime( 155 "All valid classes must have the same number of " + 156 "primary key columns\n" + 157 first + " has " + firstPk.length + "\n" + 158 cmd + " has " + len + "\n" + 159 field.fmd.jdoField.getContext()); 160 } 161 } 162 } 163 164 classIdCol = mdb.createColumn(classIdColExt == null ? null : classIdColExt.nested, 166 fieldName, stringClassIds ? String .class : Integer .class); 167 168 if (colsList.isEmpty()) { 170 if (firstPk != null) { 171 for (int i = 0; i < firstPk.length; i++) { 172 JdbcColumn c = mdb.createColumn(null, firstPk[i]); 173 c.pk = false; 174 colsList.add(c); 175 } 176 } else { 177 colsList.add(mdb.createColumn(null, fieldName, Integer .class)); 178 } 179 } else if (firstPk != null && colsList.size() != firstPk.length) { 180 throw BindingSupportImpl.getInstance().runtime( 181 "Mismatched reference column(s): " + 182 colsList.size() + " reference column(s) defined but " + 183 "valid classes have " + firstPk.length + 184 " primary key column(s)\n" + 185 field.fmd.jdoField.getContext()); 186 } 187 188 pkCols = new JdbcColumn[colsList.size()]; 189 colsList.toArray(pkCols); 190 colsList.add(0, classIdCol); 191 cols = new JdbcColumn[colsList.size()]; 192 colsList.toArray(cols); 193 } 194 195 public JdbcColumn getClassIdCol() { 196 return classIdCol; 197 } 198 199 public JdbcColumn[] getPkCols() { 200 return pkCols; 201 } 202 203 public JdbcColumn[] getCols() { 204 return cols; 205 } 206 207 public ArrayList getColsList() { 208 return colsList; 209 } 210 211 214 public ClassIdTranslator getClassIdTranslator() { 215 return classIdTranslator; 216 } 217 218 private void processClassIdMapping(JdoExtension e) { 219 String value = e.getString(); 220 int i = value.indexOf('='); 221 String cname = i < 0 ? value : value.substring(0, i); 222 String id = i < 0 ? null : value.substring(i + 1); 223 ClassMetaData key = mdb.getJmd().getClassMetaData( 224 field.fmd.classMetaData, cname); 225 if (key == null) { 226 throw BindingSupportImpl.getInstance().runtime("No persistent class found for '" + 227 cname + "': " + e + "\n" + e.getContext()); 228 } 229 if (cmdToIDString.containsKey(key)) { 230 throw BindingSupportImpl.getInstance().runtime("Duplicate class in mapping '" + 231 cname + "': " + e + "\n" + e.getContext()); 232 } 233 if (id == null || id.length() == 0) id = Integer.toString(key.classId); 234 if (classIdSet.contains(id)) { 235 throw BindingSupportImpl.getInstance().runtime("Duplicate class-id in mapping '" + 236 id + "': " + e + "\n" + e.getContext()); 237 } 238 cmdToIDString.put(key, id); 239 classIdSet.add(id); 240 } 241 242 } 243 | Popular Tags |