So the problem is that if I don't delimit column names,
DBIdentifierUtilImpl.makeIdentifierValid (called from
dict.getValidColumnName) will  convert them to upper case, whether I want it
or not. The ugly solution I came up with is to delimit them and strip the
delimiters later. Unfortunately, this leads to code duplication :( This is
what I have at the moment:


package ru.focusmedia.odp.server.datastore.jpa.impl;

import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.Normalizer;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.ValueMapping;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.persistence.jdbc.PersistenceMappingDefaults;

public class ImprovedMappingDefaults extends PersistenceMappingDefaults {
        @Override
        protected void correctName(Table table, Column col) {
                String originalName = col.getIdentifier().getName();
                boolean wasOriginallyDelimited = 
Normalizer.isDelimited(originalName);
                DBIdentifier name = DBIdentifier.newColumn(originalName,
                                !wasOriginallyDelimited);
                DBIdentifier validName = dict.getValidColumnName(name, table);
                validName = addUnderscores(validName, wasOriginallyDelimited);
                col.setIdentifier(validName);
                table.addCorrectedColumnName(validName, true);
        }

        @Override
        public void populateJoinColumn(FieldMapping fm, Table local, Table 
foreign,
                        Column col, Object target, int pos, int cols) {
                if (!(target instanceof Column))
                        return;

                // if this is a bidi relation, prefix with inverse field name, 
else
                // prefix with owning entity name
                FieldMapping[] inverses = fm.getInverseMappings();
                DBIdentifier sName = DBIdentifier.NULL;
                String originalName = inverses.length > 0 ? 
inverses[0].getName() : fm
                                .getDefiningMapping().getTypeAlias();
                boolean wasOriginallyDelimited = 
Normalizer.isDelimited(originalName);
                sName = DBIdentifier.newColumn(originalName, 
!wasOriginallyDelimited);
                DBIdentifier targetName = ((Column) target).getIdentifier();
                DBIdentifier tempName = DBIdentifier.NULL;
                if ((sName.length() + targetName.length()) >= 
dict.maxColumnNameLength) {
                        tempName = DBIdentifier.truncate(sName, 
dict.maxColumnNameLength
                                        - targetName.length() - 1);
                }
                // suffix with '_' + target column
                if (DBIdentifier.isNull(tempName))
                        tempName = sName;
                sName = DBIdentifier.combine(tempName, targetName.getName());
                sName = dict.getValidColumnName(sName, foreign);
                sName = addUnderscores(sName, wasOriginallyDelimited);
                col.setIdentifier(sName);
        }

    @Override
        public void populateForeignKeyColumn(ValueMapping vm, DBIdentifier 
sName,
            Table local, Table foreign, Column col, Object target, boolean
inverse,
            int pos, int cols) {
            boolean elem = vm == vm.getFieldMapping().getElement()
                && vm.getFieldMapping().getTypeCode() != JavaTypes.MAP;

            // if this is a non-inverse collection element key, it must be
in
            // a join table: if we're not prepending the field name, leave
the
            // default
            if (!getPrependFieldNameToJoinTableInverseJoinColumns() &&
!inverse && elem)
                return;

            // otherwise jpa always uses <field>_<pkcol> for column name,
even
            // when only one col
            if (target instanceof Column) {
                if (DBIdentifier.isNull(sName)) {
                    sName = col.getIdentifier();
                } else {
                        String originalName = elem ? 
vm.getFieldMapping().getName() :
Normalizer.removeHungarianNotation(sName.getName());
                        boolean wasOriginallyDelimited =
Normalizer.isDelimited(originalName);
                        sName = DBIdentifier.newColumn(originalName,
!wasOriginallyDelimited);
                    sName = DBIdentifier.combine(sName,
((Column)target).getIdentifier().getName());

                    // No need to check for uniqueness.
                    sName = dict.getValidColumnName(sName, local, false);
                        sName = addUnderscores(sName, wasOriginallyDelimited);
               }
                col.setIdentifier(sName);
            }
        }

        private DBIdentifier addUnderscores(DBIdentifier sName,
                        boolean wasOriginallyDelimited) {
                String nameWithUnderscores = addUnderscores(sName.getName());
                if (!wasOriginallyDelimited) {
                        nameWithUnderscores = Normalizer
                                        .removeDelimiters(nameWithUnderscores);
                }
                sName = DBIdentifier.newColumn(nameWithUnderscores, false);
                return sName;
        }
        
        // taken from Hibernate's ImprovedNamingStrategy
        private static String addUnderscores(String name) {
                StringBuilder buf = new StringBuilder(name.replace('.', '_'));
                for (int i = 1; i < buf.length() - 1; i++) {
                        if (Character.isLowerCase(buf.charAt(i - 1))
                                        && Character.isUpperCase(buf.charAt(i))
                                        && Character.isLowerCase(buf.charAt(i + 
1))) {
                                buf.insert(i++, '_');
                        }
                }
                return buf.toString().toLowerCase();
        }
}


--
View this message in context: 
http://openjpa.208410.n2.nabble.com/Change-of-MappingDefaults-breaks-OPENJPA-SEQUENCE-TABLE-tp7580246p7580270.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Reply via email to