/* * Copyright 2015 JAXIO http://www.jaxio.com * * 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. */ package com.jaxio.jpa.querybyexample; import com.google.common.base.Splitter; import javax.enterprise.context.ApplicationScoped; import javax.inject.Named; import javax.persistence.*; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.SingularAttribute; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.util.Collection; import java.util.List; import java.util.Map; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; @ApplicationScoped @Named public class MetamodelUtil { private static MetamodelUtil instance; public static MetamodelUtil getInstance() { return instance; } private Map<Class<?>, Class<?>> metamodelCache = newHashMap(); public MetamodelUtil() { instance = this; } public SingularAttribute<?, ?> toAttribute(String property, Class<?> from) { try { Class<?> metamodelClass = getCachedClass(from); Field field = metamodelClass.getField(property); return (SingularAttribute<?, ?>) field.get(null); } catch (Exception e) { throw new IllegalArgumentException(e); } } public List<Attribute<?, ?>> toAttributes(String path, Class<?> from) { try { List<Attribute<?, ?>> attributes = newArrayList(); Class<?> current = from; for (String pathItem : Splitter.on(".").split(path)) { Class<?> metamodelClass = getCachedClass(current); Field field = metamodelClass.getField(pathItem); Attribute<?, ?> attribute = (Attribute<?, ?>) field.get(null); attributes.add(attribute); if (attribute instanceof PluralAttribute) { current = ((PluralAttribute<?, ?, ?>) attribute).getElementType().getJavaType(); } else { current = attribute.getJavaType(); } } return attributes; } catch (Exception e) { throw new IllegalArgumentException(e); } } public String toPath(List<Attribute<?, ?>> attributes) { StringBuilder path = new StringBuilder(); for (Attribute<?, ?> attribute : attributes) { if (path.length() > 0) { path.append("."); } path.append(attribute.getName()); } return path.toString(); } private Class<?> getCachedClass(Class<?> current) throws ClassNotFoundException { if (metamodelCache.containsKey(current)) { return metamodelCache.get(current); } Class<?> metamodelClass = Class.forName(current.getName() + "_"); metamodelCache.put(current, metamodelClass); return metamodelClass; } /** * Retrieves cascade from metamodel attribute * * @param attribute given pluaral attribute * @return an empty collection if no jpa relation annotation can be found. */ public Collection<CascadeType> getCascades(PluralAttribute<?, ?, ?> attribute) { if (attribute.getJavaMember() instanceof AccessibleObject) { AccessibleObject accessibleObject = (AccessibleObject) attribute.getJavaMember(); OneToMany oneToMany = accessibleObject.getAnnotation(OneToMany.class); if (oneToMany != null) { return newArrayList(oneToMany.cascade()); } ManyToMany manyToMany = accessibleObject.getAnnotation(ManyToMany.class); if (manyToMany != null) { return newArrayList(manyToMany.cascade()); } } return newArrayList(); } /** * Retrieves cascade from metamodel attribute on a xToMany relation. * * @param attribute given singular attribute * @return an empty collection if no jpa relation annotation can be found. */ public Collection<CascadeType> getCascades(SingularAttribute<?, ?> attribute) { if (attribute.getJavaMember() instanceof AccessibleObject) { AccessibleObject accessibleObject = (AccessibleObject) attribute.getJavaMember(); OneToOne oneToOne = accessibleObject.getAnnotation(OneToOne.class); if (oneToOne != null) { return newArrayList(oneToOne.cascade()); } ManyToOne manyToOne = accessibleObject.getAnnotation(ManyToOne.class); if (manyToOne != null) { return newArrayList(manyToOne.cascade()); } } return newArrayList(); } public boolean isOrphanRemoval(PluralAttribute<?, ?, ?> attribute) { if (attribute.getJavaMember() instanceof AccessibleObject) { AccessibleObject accessibleObject = (AccessibleObject) attribute.getJavaMember(); OneToMany oneToMany = accessibleObject.getAnnotation(OneToMany.class); if (oneToMany != null) { return oneToMany.orphanRemoval(); } } return true; } }