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.expr.Expression; 019import japa.parser.ast.expr.MemberValuePair; 020import japa.parser.ast.expr.NameExpr; 021import japa.parser.ast.expr.NormalAnnotationExpr; 022import japa.parser.ast.expr.StringLiteralExpr; 023import org.apache.commons.lang.StringUtils; 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026import org.apache.ojb.broker.metadata.ClassDescriptor; 027import org.apache.ojb.broker.metadata.DescriptorRepository; 028import org.apache.ojb.broker.metadata.FieldDescriptor; 029import org.apache.ojb.broker.metadata.ObjectReferenceDescriptor; 030import org.kuali.rice.devtools.jpa.eclipselink.conv.ojb.OjbUtil; 031 032import java.util.ArrayList; 033import java.util.Collection; 034import java.util.List; 035 036/** 037 * this only does mappings for OneToOne at the field level for compound fks. 038 */ 039public abstract class AbstractPrimaryKeyJoinColumnResolver extends AbstractMappedFieldResolver { 040 private static final Log LOG = LogFactory.getLog(AbstractPrimaryKeyJoinColumnResolver.class); 041 042 public AbstractPrimaryKeyJoinColumnResolver(Collection<DescriptorRepository> descriptorRepositories) { 043 super(descriptorRepositories); 044 } 045 046 protected final List<Expression> getJoinColumns(String enclosingClass, String fieldName, String mappedClass) { 047 final ObjectReferenceDescriptor ord = OjbUtil.findObjectReferenceDescriptor(mappedClass, fieldName, 048 descriptorRepositories); 049 final List<Expression> joinColumns = new ArrayList<Expression>(); 050 051 if (foundDescriptor(ord)) { 052 053 final Collection<String> fks = getForeignKeys(ord); 054 if (fks == null || fks.isEmpty()) { 055 LOG.error(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a reference descriptor for " + fieldName 056 + " but does not have any foreign keys configured"); 057 return null; 058 } 059 060 final Collection<String> pks = OjbUtil.getPrimaryKeyNames(mappedClass, descriptorRepositories); 061 062 if (pks.size() == fks.size() && pks.containsAll(fks) && !pks.isEmpty()) { 063 064 final ClassDescriptor cd = OjbUtil.findClassDescriptor(mappedClass, descriptorRepositories); 065 final ClassDescriptor icd; 066 067 final String itemClassName = getItemClass(ord); 068 if (StringUtils.isBlank(itemClassName)) { 069 LOG.error(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a reference descriptor for " + fieldName 070 + " but does not class name attribute"); 071 return null; 072 } else { 073 icd = OjbUtil.findClassDescriptor(itemClassName, descriptorRepositories); 074 } 075 076 final FieldDescriptor[] pfds = cd.getPkFields(); 077 final FieldDescriptor[] ipfds = icd.getPkFields(); 078 for (int i = 0; i < pfds.length; i++) { 079 final List<MemberValuePair> pairs = new ArrayList<MemberValuePair>(); 080 pairs.add(new MemberValuePair("name", new StringLiteralExpr(pfds[i].getColumnName()))); 081 pairs.add(new MemberValuePair("referencedColumnName", new StringLiteralExpr(ipfds[i].getColumnName()))); 082 joinColumns.add(new NormalAnnotationExpr(new NameExpr("PrimaryKeyJoinColumn"), pairs)); 083 } 084 085 if (isCascadeDelete(ord)) { 086 LOG.error(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a reference descriptor set to cascade delete but JPA does not support that configuration with primary key join columns."); 087 } 088 if (isCascadePersist(ord)) { 089 LOG.error(ResolverUtil.logMsgForField(enclosingClass, fieldName, mappedClass) + " field has a reference descriptor set to cascade persist but JPA does not support that configuration with primary key join columns."); 090 } 091 } 092 } 093 return joinColumns; 094 } 095 096 private boolean foundDescriptor(ObjectReferenceDescriptor ord) { 097 return ord != null; 098 } 099 100 private List<String> getForeignKeys(ObjectReferenceDescriptor ord) { 101 if (ord != null) { 102 return ord.getForeignKeyFields(); 103 } 104 return null; 105 } 106 107 private String getItemClass(ObjectReferenceDescriptor ord) { 108 if (ord != null) { 109 return ord.getItemClassName(); 110 } 111 return null; 112 } 113 114 private boolean isCascadeDelete(ObjectReferenceDescriptor ord) { 115 return ord.getCascadingDelete() == ObjectReferenceDescriptor.CASCADE_OBJECT; 116 } 117 118 private boolean isCascadePersist(ObjectReferenceDescriptor ord) { 119 return ord.getCascadingStore() == ObjectReferenceDescriptor.CASCADE_OBJECT; 120 } 121}