001/**
002 * Copyright 2005-2016 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.devtools.jpa.eclipselink.conv.parser.helper.resolver;
017
018import japa.parser.ast.ImportDeclaration;
019import japa.parser.ast.expr.MemberValuePair;
020import japa.parser.ast.expr.NameExpr;
021import japa.parser.ast.expr.NormalAnnotationExpr;
022import japa.parser.ast.expr.QualifiedNameExpr;
023import org.apache.commons.lang.ClassUtils;
024import org.apache.commons.lang.StringUtils;
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.apache.ojb.broker.accesslayer.conversions.FieldConversion;
028import org.apache.ojb.broker.accesslayer.conversions.FieldConversionDefaultImpl;
029import org.apache.ojb.broker.metadata.DescriptorRepository;
030import org.apache.ojb.broker.metadata.FieldDescriptor;
031import org.kuali.rice.devtools.jpa.eclipselink.conv.ojb.OjbUtil;
032import org.kuali.rice.devtools.jpa.eclipselink.conv.parser.helper.NodeData;
033
034import java.util.Collection;
035import java.util.Collections;
036import java.util.Map;
037
038public class ConvertResolver extends AbstractMappedFieldResolver {
039    private static final Log LOG = LogFactory.getLog(ConvertResolver.class);
040
041    public static final String PACKAGE = "javax.persistence";
042    public static final String SIMPLE_NAME = "Convert";
043
044    private Map<String,String> converterMappings;
045
046    public ConvertResolver(Collection<DescriptorRepository> descriptorRepositories, Map<String,String> converterMappings) {
047        super(descriptorRepositories);
048        this.converterMappings = converterMappings;
049    }
050
051    @Override
052    public String getFullyQualifiedName() {
053        return PACKAGE + "." + SIMPLE_NAME;
054    }
055
056    private String getJpaConverterForOjbClass( String ojbConverter ) {
057        for ( String key : converterMappings.keySet() ) {
058            // Substring match
059            if ( ojbConverter.contains(key) ) {
060                return converterMappings.get(key);
061            }
062        }
063        return null;
064    }
065    
066    /** gets the annotation but also adds an import in the process if a Convert annotation is required. */
067    @Override
068    protected NodeData getAnnotationNodes(String enclosingClass, String fieldName, String mappedClass) {
069        final FieldDescriptor fd = OjbUtil.findFieldDescriptor(mappedClass, fieldName, descriptorRepositories);
070
071        if (fd != null) {
072            final FieldConversion fc = fd.getFieldConversion();
073            //in ojb all columns have at least the default field conversion
074            if (fc != null && FieldConversionDefaultImpl.class != fc.getClass()) {
075                LOG.info(enclosingClass + "." + fieldName + " for the mapped class " + mappedClass + " field has a converter " + fc.getClass().getName());
076
077                final String jpaConverter = getJpaConverterForOjbClass(fc.getClass().getName());
078                if (jpaConverter == null) {
079                    LOG.error(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a converter " + fc.getClass().getName()
080                        + " but a replacement converter was not configured, unable to set Convert class");
081                    return new NodeData(new NormalAnnotationExpr(new NameExpr(SIMPLE_NAME), Collections.singletonList(new MemberValuePair("converter", new NameExpr(null)))),
082                            new ImportDeclaration(new QualifiedNameExpr(new NameExpr(PACKAGE), SIMPLE_NAME), false, false));
083                } else if ( StringUtils.isBlank(jpaConverter) ) {
084                    LOG.info(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a converter " + fc.getClass().getName()
085                            + " But no converter definition is needed due to default converter configuration." );
086                } else {
087                    final String shortClassName = ClassUtils.getShortClassName(jpaConverter);
088                    final String packageName = ClassUtils.getPackageName(jpaConverter);
089                    return new NodeData(new NormalAnnotationExpr(new NameExpr(SIMPLE_NAME),  Collections.singletonList(new MemberValuePair("converter", new NameExpr(shortClassName + ".class")))),
090                            new ImportDeclaration(new QualifiedNameExpr(new NameExpr(PACKAGE), SIMPLE_NAME), false, false),
091                            Collections.singletonList(new ImportDeclaration(new QualifiedNameExpr(new NameExpr(packageName), shortClassName), false, false)));
092                }
093            }
094        }
095        return null;
096    }
097}