| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.openjpa.jdbc.meta; |
| |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.TreeSet; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.apache.openjpa.jdbc.schema.Column; |
| import org.apache.openjpa.jdbc.schema.ForeignKey; |
| import org.apache.openjpa.jdbc.schema.Table; |
| import org.apache.openjpa.lib.util.Localizer; |
| import serp.util.Strings; |
| |
| /** |
| * Simple {@link ReverseCustomizer} that uses a properties file to |
| * to allow customization of basic class and field properties. The |
| * customizer uses the following keys: |
| * <ul> |
| * <li><i><table name>.table-type</i>: Override the default type of the |
| * given table. Legal values are: <code>base, secondary, |
| * secondary-outer, association, subclass, none</code>. See |
| * the TABLE_XXX constants in {@link ReverseMappingTool} for descriptions.</li> |
| * <li><i><class name>.rename</i>: Override the tool-generated class name |
| * with the given value. Use full class names, including package. Use a |
| * value of <code>none</code> to reject the class and leave the |
| * corresponding table unmapped.</li> |
| * <li><i><table name>.class-name</i>: Assign the given fully-qualified |
| * class name to the type created from the given table. Use a value of |
| * <code>none</code> to prevent mapping this table. This property can be |
| * used in place of the <code>rename</code> property. |
| * <li><i><class name>.identity</i>: Set this property to |
| * <code>datastore</code>, <code>builtin</code>, or the desired |
| * fully-qualified application identity class name to override the |
| * reverse mapping tool's default identity settings. If the class has been |
| * renamed, use the new name.</li> |
| * <li><i><class name>.<field name>.rename</i>: Override the |
| * tool-generated field name with the given value. Use the field owner's |
| * full class name in the property key. The property value should be the |
| * new field name, without the preceding class name. Use a value of |
| * <code>none</code> to reject the generated mapping.</li> |
| * <li><i><table name>.<column name>.field-name</i>: Assign the |
| * field name to use for the mapping of a particular column. If this is |
| * a multi-column mapping, any one of the columns can be used. Use a value |
| * of <code>none</code> to prevent the column (and associated columns) |
| * from being mapped. This property can be used in place of the |
| * <code>rename</code> property. |
| * <li><i><class name>.<field name>.type</i>: The class name of |
| * the type to give the named field. Use full class names. If the field |
| * has been renamed, use the new name.</li> |
| * <li><i><class name>.<field name>.value</i>: The initial value |
| * for the named field. The given string will be placed as-is in the |
| * generated Java code, so be sure to add quotes to strings, etc. If the |
| * field has been renamed, use the new name.</li> |
| * </ul> All keys are optional; if not specified, the customizer keeps the |
| * default value generated by the reverse mapping tool. |
| */ |
| public class PropertiesReverseCustomizer |
| implements ReverseCustomizer { |
| |
| private static final Localizer _loc = Localizer.forPackage |
| (PropertiesReverseCustomizer.class); |
| |
| protected ReverseMappingTool tool = null; |
| private Properties _props = null; |
| private Set _unaccessed = null; |
| |
| public void setConfiguration(Properties props) { |
| _props = props; |
| _unaccessed = new TreeSet(props.keySet()); |
| } |
| |
| public void setTool(ReverseMappingTool tool) { |
| this.tool = tool; |
| } |
| |
| public int getTableType(Table table, int defaultType) { |
| String type = getProperty(table.getName() + ".table-type"); |
| if (type == null && table.getSchemaName() != null) |
| type = getProperty(table.getFullName() + ".table-type"); |
| if (type == null) |
| return defaultType; |
| if ("none".equals(type)) |
| return ReverseMappingTool.TABLE_NONE; |
| if ("base".equals(type)) |
| return ReverseMappingTool.TABLE_BASE; |
| if ("secondary".equals(type)) |
| return ReverseMappingTool.TABLE_SECONDARY; |
| if ("secondary-outer".equals(type)) |
| return ReverseMappingTool.TABLE_SECONDARY_OUTER; |
| if ("association".equals(type)) |
| return ReverseMappingTool.TABLE_ASSOCIATION; |
| if ("subclass".equals(type)) |
| return ReverseMappingTool.TABLE_SUBCLASS; |
| throw new IllegalArgumentException(table.getName() + ".table-type: " |
| + type); |
| } |
| |
| public String getClassName(Table table, String defaultName) { |
| // check for a rename property or a table-naming property |
| String name = getProperty(defaultName + ".rename"); |
| if (name == null) { |
| name = getProperty(table.getName() + ".class-name"); |
| if (name == null && table.getSchemaName() != null) |
| name = getProperty(table.getFullName() + ".class-name"); |
| } |
| |
| if (name == null) { |
| if (tool.getLog().isTraceEnabled()) |
| tool.getLog().trace(_loc.get("custom-no-class", |
| defaultName, table)); |
| return defaultName; |
| } |
| |
| if ("none".equals(name)) { |
| if (tool.getLog().isInfoEnabled()) |
| tool.getLog().info(_loc.get("custom-rm-class", |
| defaultName, table)); |
| return null; |
| } |
| |
| if (tool.getLog().isInfoEnabled()) |
| tool.getLog().info(_loc.get("custom-class", defaultName, name)); |
| return name; |
| } |
| |
| public void customize(ClassMapping cls) { |
| // customize identity type |
| String id = getProperty(cls.getDescribedType().getName() |
| + ".identity"); |
| if ("datastore".equals(id)) { |
| cls.setObjectIdType(null, false); |
| cls.setIdentityType(ClassMapping.ID_DATASTORE); |
| } else if ("builtin".equals(id)) { |
| cls.setObjectIdType(null, false); |
| cls.setIdentityType(ClassMapping.ID_APPLICATION); |
| } else if (id != null) |
| cls.setObjectIdType(tool.generateClass(id, null), false); |
| } |
| |
| public String getClassCode(ClassMapping mapping) { |
| return null; |
| } |
| |
| public void customize(FieldMapping field) { |
| String type = getProperty(field.getFullName(false) + ".type"); |
| if (type != null) |
| field.setDeclaredType(Strings.toClass(type, null)); |
| } |
| |
| public String getFieldName(ClassMapping dec, Column[] cols, ForeignKey fk, |
| String defaultName) { |
| // check for a rename property or a column-naming property |
| String name = getProperty(dec.getDescribedType().getName() + "." |
| + defaultName + ".rename"); |
| for (int i = 0; name == null && i < cols.length; i++) { |
| name = getProperty(cols[i].getTableName() + "." |
| + cols[i].getName() + "." + "field-name"); |
| if (name == null && cols[i].getTable().getSchemaName() != null) |
| name = getProperty(cols[i].getTable().getFullName() |
| + "." + cols[i].getName() + "." + "field-name"); |
| } |
| |
| if (name == null) { |
| if (tool.getLog().isTraceEnabled()) |
| tool.getLog().trace(_loc.get("custom-no-field", defaultName, |
| dec)); |
| return defaultName; |
| } |
| |
| if ("none".equals(name)) { |
| if (tool.getLog().isInfoEnabled()) |
| tool.getLog().info(_loc.get("custom-rm-field", defaultName, |
| dec)); |
| return null; |
| } |
| |
| if (tool.getLog().isInfoEnabled()) |
| tool.getLog().info(_loc.get("custom-field", defaultName, dec, |
| name)); |
| return name; |
| } |
| |
| public String getInitialValue(FieldMapping field) { |
| return getProperty(field.getFullName(false) + ".value"); |
| } |
| |
| public String getDeclaration(FieldMapping field) { |
| return null; |
| } |
| |
| public String getFieldCode(FieldMapping field) { |
| return null; |
| } |
| |
| public boolean unmappedTable(Table table) { |
| return false; |
| } |
| |
| public void close() { |
| if (!_unaccessed.isEmpty() && tool.getLog().isTraceEnabled()) |
| tool.getLog().trace(_loc.get("custom-unused-props", _unaccessed)); |
| } |
| |
| /** |
| * Return the property value for the given key, or null if none. |
| */ |
| protected String getProperty(String key) { |
| String val = StringUtils.trimToNull(_props.getProperty(key)); |
| _unaccessed.remove(key); |
| return val; |
| } |
| } |