1 22 23 package org.xquark.mapper.mapping; 24 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 import org.xml.sax.SAXException ; 28 import org.xquark.jdbc.typing.ColumnMetaData; 29 import org.xquark.mapping.Generator; 30 import org.xquark.mapping.UserGenerator; 31 import org.xquark.schema.*; 32 import org.xquark.xml.xdbc.XMLDBCException; 33 import org.xquark.xml.xdbc.XMLErrorHandler; 34 35 39 class ColumnMappingImpl extends MappingImpl 40 implements ColumnMapping, MappingConstants 41 { 42 private static final String RCSRevision = "$Revision: 1.7 $"; 43 private static final String RCSName = "$Name: $"; 44 45 private static Log log = LogFactory.getLog(ColumnMappingImpl.class); 46 47 private TableMappingImpl tableMapping; 48 private String name; 49 private int index; 50 private int keyColumnIndex = -1; 51 private int keyGenColumnIndex = -1; 52 private int joinColumnIndex = -1; 53 private int primaryKeyColumnIndex = -1; 54 private int insertColumnIndex = -1; 55 private int selectColumnIndex = -1; 56 private int fetchColumnIndex = -1; 57 private int updateColumnIndex = -1; 58 private Generator generator; 59 private MappingTypeInfo typeInfo; 60 64 private Generator defaultGenerator = null; 65 private int tableRefIndex = -1; 66 private int minOccurs; 67 private boolean updateColumnWhenMissing = false; 68 private XMLErrorHandler messageHandler = null; 70 ColumnMappingImpl(TableMappingImpl tableMapping, SchemaComponent comp, 71 int minOccurs, String name, int role, Generator generator, 72 XMLErrorHandler messageHandler) 73 throws SAXException 74 { 75 super(comp); 76 this.name = name; 77 this.tableMapping = tableMapping; 78 this.messageHandler = messageHandler; 79 index = tableMapping.register(this); 80 this.minOccurs = minOccurs; 81 insertColumnIndex = tableMapping.incrementColumnMappingCount(); 82 ColumnMetaData cmeta = getMetaData(); 83 if (cmeta != null) { 84 if (cmeta.isPrimaryKey()) { 85 keyColumnIndex = tableMapping.incrementKeyColumnCount(); 86 } 87 } 88 if ((role & KEY_ROLE) != 0) { 90 if ((cmeta != null) && cmeta.isLongType()) 91 throw new SAXException ("A column with a long datatype cannot be \"inKey\"."); 92 keyGenColumnIndex = tableMapping.incrementKeyGenColumnCount(); 93 } 94 if ((role & SELECT_ROLE) != 0) 95 { 96 if ((cmeta != null) && cmeta.isLongType() && (tableMapping.getAction() != INSERT)) 97 throw new SAXException ("A column with a long datatype cannot be \"inSelect\"."); 98 selectColumnIndex = tableMapping.incrementSelectColumnCount(); 99 } 100 else { 101 fetchColumnIndex = tableMapping.incrementFetchColumnCount(); 102 if ((role & KEY_ROLE) == 0) updateColumnIndex = tableMapping.incrementUpdateColumnCount(); 104 } 105 if (generator != null) 106 setGenerator(generator); 107 } 108 109 ColumnMappingImpl(TableMappingImpl tableMapping, SchemaComponent comp, 110 int minOccurs, String name, int role, Generator generator, 111 boolean updateColumnWhenMissing, XMLErrorHandler messageHandler) 112 throws SAXException { 113 this(tableMapping, comp, minOccurs, name, role, generator, messageHandler); 114 this.updateColumnWhenMissing = updateColumnWhenMissing; 115 } 116 117 public String toString() { 118 return getTableName()+"."+name; 119 } 120 121 public String getTableName() { return tableMapping.getTableName();} 122 123 public int getTableIndex() { return tableMapping.getTableIndex();} 124 125 public String getColumnName() { return name;} 126 127 public boolean isInJoin() { return joinColumnIndex > -1;} 128 129 public int getJoinColumnIndex() { return joinColumnIndex;} 130 131 public ColumnMetaData getMetaData() 132 { 133 TableMetaData tmeta = tableMapping.getMetaData(); 134 if (tmeta == null) return null; 135 return tmeta.getColumnMetaData(name); 136 } 137 138 public int getColumnIndex() { return index; } 139 140 public int getInsertColumnIndex() 141 { return insertColumnIndex; } 142 143 public int getKeyColumnIndex() 144 { 145 return keyColumnIndex; 146 } 147 148 public int getSelectColumnIndex() { return selectColumnIndex;} 149 150 public int getFetchColumnIndex() { return fetchColumnIndex;} 151 152 public int getUpdateColumnIndex() { return updateColumnIndex;} 153 154 public Generator getGenerator() { return generator;} 155 156 public MappingTypeInfo getTypeInfo() { return typeInfo;} 157 158 public int getKeyGenColumnIndex() {return keyGenColumnIndex;} 159 160 public Generator getDefaultGenerator() { return defaultGenerator;} 161 162 public Generator getInitGenerator() { 163 return defaultGenerator == null ? generator : defaultGenerator; 164 } 165 166 public int getTableRefIndex() { return tableRefIndex; } 167 168 public int getColumnType() { return getMetaData().getDataType();} 169 170 int getMinOccurs() { return minOccurs;} 171 172 void setKeyColumnIndex(int index) { keyColumnIndex = index;} 173 174 public void setJoinColumnIndex(int index) {joinColumnIndex = index;} 175 176 void setGenerator(Generator generator) throws SAXException 177 { 178 this.generator = generator; 179 180 if (comp == null) setTableMappingGenerator(generator); 182 else checkOccurrenceConstraints(minOccurs); 185 if (generator instanceof UserGenerator) 186 typeInfo = new MappingTypeInfo(((UserGenerator)generator).getXMLType()); 187 else if (generator instanceof ValueGenerator) 188 { 189 Type type; 190 if (comp instanceof Declaration) 191 type = ((Declaration)comp).getType(); 192 else 193 type = (Type)comp; 194 typeInfo = new MappingTypeInfo(type.getValueType()); 195 ((ValueGenerator)generator).setTypeInfo(typeInfo); 196 } 197 else { 199 ColumnMapping refColumn = null; 200 if (generator instanceof ColumnRefGenerator) 201 refColumn = ((ColumnRefGenerator)generator).getColumnRef(); 202 if (refColumn != null) 203 typeInfo = refColumn.getTypeInfo(); 204 if (typeInfo == null) 205 throw new SAXException ("Cannot reference a ref generator in column " 206 + getMetaData() 207 +". Please directly reference the column referenced by the ref generator"); 208 } 209 210 checkTypeConstraints(); 211 } 212 213 private void setDefaultGenerator(Generator generator) { 214 defaultGenerator = generator; 215 tableMapping.addToInitialValues(this); 216 } 217 218 void setTableMappingGenerator(Generator generator) 219 { 220 if (generator instanceof ValueGenerator || generator instanceof ColumnRefGenerator) 221 tableMapping.addToFinalValues(this); else 223 tableMapping.addToInitialValues(this); 224 } 225 226 private void checkOccurrenceConstraints(int minOccurs) 227 throws SAXException 228 { 229 ColumnMetaData cmeta = getMetaData(); 230 if (cmeta != null) { 231 SchemaComponent comp = getSchemaComponent(); 232 if (minOccurs == 0) { 233 String defVal = cmeta.getDefaultValue(); 234 if (defVal != null) 235 setDefaultGenerator(new ConstantGenerator(defVal)); 236 else if (cmeta.isNullable()) 237 setDefaultGenerator(new ConstantGenerator(null)); 238 else 239 throw new SAXException ("Optional element or attribute "+comp 240 +" cannot be mapped onto " +cmeta 241 +". The column should be nullable or have a default value"); 242 } 243 if (comp instanceof ElementDeclaration 244 && ((ElementDeclaration)comp).isNillable() 245 && !cmeta.isNullable()) 246 throw new SAXException ("Nullable element "+comp 247 +"cannot be mapped onto the non-nullable " 248 +cmeta); 249 } 250 } 251 252 private void checkTypeConstraints() 253 throws SAXException 254 { 255 ColumnMetaData cmeta = getMetaData(); 256 if (cmeta != null) { 257 if (cmeta.getRefTable() == null) { 258 if (generator instanceof ColumnRefGenerator) 259 this.tableRefIndex = (((ColumnRefGenerator)generator).getColumnRef()).getTableIndex(); 261 } 262 else { 263 if (generator instanceof ColumnRefGenerator) 264 { 265 ColumnMapping refCol = ((ColumnRefGenerator)generator).getColumnRef(); 266 if (!refCol.getTableName().equals(cmeta.getRefTable()) 267 || !refCol.getColumnName().equals(cmeta.getRefColumn())) 268 throw new SAXException ("The reference mapping from " 269 + cmeta + " to " 270 + refCol.getMetaData() + 271 " is not consistent with existing foreign key constraints"); 272 this.tableRefIndex = refCol.getTableIndex(); 274 } 275 else 276 { 277 try 278 { 279 XMLDBCException ex = new XMLDBCException("The mapping for " 280 + cmeta + " is not consistent with existing foreign key constraints"); 281 if (messageHandler != null) 282 messageHandler.warning(ex); 283 log.warn(ex.getMessage()); 284 } 285 catch (XMLDBCException e) 286 { 287 throw new SAXException ("User abort", e); 288 } 289 } 290 } 291 typeInfo.checkTargetType(cmeta, messageHandler); 292 } else if (generator instanceof ColumnRefGenerator) { 294 this.tableRefIndex = ((ColumnRefGenerator)generator).getColumnRef().getTableIndex(); 296 } 297 } 298 299 public TableMapping getTableMapping() { return tableMapping;} 300 301 304 public boolean updateColumnWhenMissing() { return updateColumnWhenMissing;} 305 } 306 | Popular Tags |