/*
* #%L
* BroadleafCommerce Open Admin Platform
* %%
* Copyright (C) 2009 - 2013 Broadleaf Commerce
* %%
* Licensed 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.
* #L%
*/
package org.broadleafcommerce.openadmin.server.dao.provider.metadata;
import org.apache.commons.lang.StringUtils;
import org.broadleafcommerce.common.persistence.EntityConfiguration;
import org.broadleafcommerce.common.presentation.AdminPresentationClass;
import org.broadleafcommerce.common.presentation.OptionFilterParamType;
import org.broadleafcommerce.common.presentation.client.SupportedFieldType;
import org.broadleafcommerce.common.presentation.override.AdminPresentationMergeEntry;
import org.broadleafcommerce.common.util.Tuple;
import org.broadleafcommerce.openadmin.dto.BasicFieldMetadata;
import org.broadleafcommerce.openadmin.dto.FieldMetadata;
import org.broadleafcommerce.openadmin.dto.override.FieldMetadataOverride;
import org.broadleafcommerce.openadmin.server.dao.DynamicEntityDao;
import org.broadleafcommerce.openadmin.server.dao.FieldInfo;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.persistence.ManyToMany;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
/**
* @author Jeff Fischer
*/
public abstract class AbstractFieldMetadataProvider implements FieldMetadataProvider {
protected Map<String, Map<String, FieldMetadataOverride>> metadataOverrides;
@Resource(name = "blEntityConfiguration")
protected EntityConfiguration entityConfiguration;
@Resource(name = "blBroadleafEnumerationUtility")
protected BroadleafEnumerationUtility enumerationUtility;
@Resource(name="blMetadataOverrides")
public void setMetadataOverrides(Map metadataOverrides) {
try {
this.metadataOverrides = metadataOverrides;
} catch (Throwable e) {
throw new IllegalArgumentException(
"Unable to assign metadataOverrides. You are likely using an obsolete spring application context " +
"configuration for this value. Please utilize the xmlns:mo=\"http://schema.broadleafcommerce.org/mo\" namespace " +
"and http://schema.broadleafcommerce.org/mo http://schema.broadleafcommerce.org/mo/mo.xsd schemaLocation " +
"in the xml schema config for your app context. This will allow you to use the appropriate <mo:override> element to configure your overrides.", e);
}
}
protected void setClassOwnership(Class<?> parentClass, Class<?> targetClass, Map<String, FieldMetadata> attributes, FieldInfo field) {
FieldMetadata metadata = attributes.get(field.getName());
if (metadata != null) {
AdminPresentationClass adminPresentationClass;
if (parentClass != null) {
metadata.setOwningClass(parentClass.getName());
adminPresentationClass = parentClass.getAnnotation(AdminPresentationClass.class);
} else {
adminPresentationClass = targetClass.getAnnotation(AdminPresentationClass.class);
}
if (adminPresentationClass != null) {
String friendlyName = adminPresentationClass.friendlyName();
if (!StringUtils.isEmpty(friendlyName) && StringUtils.isEmpty(metadata.getOwningClassFriendlyName())) {
metadata.setOwningClassFriendlyName(friendlyName);
}
}
}
}
protected FieldInfo buildFieldInfo(Field field) {
FieldInfo info = new FieldInfo();
info.setName(field.getName());
info.setGenericType(field.getGenericType());
ManyToMany manyToMany = field.getAnnotation(ManyToMany.class);
if (manyToMany != null) {
info.setManyToManyMappedBy(manyToMany.mappedBy());
info.setManyToManyTargetEntity(manyToMany.targetEntity().getName());
}
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
if (oneToMany != null) {
info.setOneToManyMappedBy(oneToMany.mappedBy());
info.setOneToManyTargetEntity(oneToMany.targetEntity().getName());
}
MapKey mapKey = field.getAnnotation(MapKey.class);
if (mapKey != null) {
info.setMapKey(mapKey.name());
}
return info;
}
/**
* @deprecated use the overloaded method that takes DynamicEntityDao as well. This version does not always properly detect the override from xml.
* @param configurationKey
* @param ceilingEntityFullyQualifiedClassname
* @return override value
*/
@Deprecated
protected Map<String, FieldMetadataOverride> getTargetedOverride(String configurationKey, String ceilingEntityFullyQualifiedClassname) {
if (metadataOverrides != null && (configurationKey != null || ceilingEntityFullyQualifiedClassname != null)) {
return metadataOverrides.containsKey(configurationKey)?metadataOverrides.get(configurationKey):metadataOverrides.get(ceilingEntityFullyQualifiedClassname);
}
return null;
}
protected Map<String, FieldMetadataOverride> getTargetedOverride(DynamicEntityDao dynamicEntityDao, String configurationKey, String ceilingEntityFullyQualifiedClassname) {
if (metadataOverrides != null && (configurationKey != null || ceilingEntityFullyQualifiedClassname != null)) {
if (metadataOverrides.containsKey(configurationKey)) {
return metadataOverrides.get(configurationKey);
}
if (metadataOverrides.containsKey(ceilingEntityFullyQualifiedClassname)) {
return metadataOverrides.get(ceilingEntityFullyQualifiedClassname);
}
Class<?> test;
try {
test = Class.forName(ceilingEntityFullyQualifiedClassname);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
if (test.isInterface()) {
//if it's an interface, get the least derive polymorphic concrete implementation
Class<?>[] types = dynamicEntityDao.getAllPolymorphicEntitiesFromCeiling(test);
return metadataOverrides.get(types[types.length-1].getName());
} else {
//if it's a concrete implementation, try the interfaces
Class<?>[] types = test.getInterfaces();
for (Class<?> type : types) {
if (metadataOverrides.containsKey(type.getName())) {
return metadataOverrides.get(type.getName());
}
}
}
}
return null;
}
protected Class<?> getBasicJavaType(SupportedFieldType fieldType) {
Class<?> response;
switch (fieldType) {
case BOOLEAN:
response = Boolean.TYPE;
break;
case DATE:
response = Date.class;
break;
case DECIMAL:
response = BigDecimal.class;
break;
case MONEY:
response = BigDecimal.class;
break;
case INTEGER:
response = Integer.TYPE;
break;
case UNKNOWN:
response = null;
break;
default:
response = String.class;
break;
}
return response;
}
protected Object convertType(String value, OptionFilterParamType type) {
Object response;
switch (type) {
case BIGDECIMAL:
response = new BigDecimal(value);
break;
case BOOLEAN:
response = Boolean.parseBoolean(value);
break;
case DOUBLE:
response = Double.parseDouble(value);
break;
case FLOAT:
response = Float.parseFloat(value);
break;
case INTEGER:
response = Integer.parseInt(value);
break;
case LONG:
response = Long.parseLong(value);
break;
default:
response = value;
break;
}
return response;
}
protected void setupBroadleafEnumeration(String broadleafEnumerationClass, BasicFieldMetadata fieldMetadata, DynamicEntityDao dynamicEntityDao) {
try {
List<Tuple<String, String>> enumVals = enumerationUtility.getEnumerationValues(broadleafEnumerationClass, dynamicEntityDao);
String[][] enumerationValues = new String[enumVals.size()][2];
int j = 0;
for (Tuple<String, String> t : enumVals) {
enumerationValues[j][0] = t.getFirst();
enumerationValues[j][1] = t.getSecond();
j++;
}
fieldMetadata.setEnumerationValues(enumerationValues);
fieldMetadata.setEnumerationClass(broadleafEnumerationClass);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
protected Map<String, AdminPresentationMergeEntry> getAdminPresentationEntries(AdminPresentationMergeEntry[] entries) {
Map<String, AdminPresentationMergeEntry> response = new HashMap<String, AdminPresentationMergeEntry>();
for (AdminPresentationMergeEntry entry : entries) {
response.put(entry.propertyType(), entry);
}
return response;
}
}