use of javassist.CtMethod in project hibernate-orm by hibernate.
the class PersistentAttributesEnhancer method handleBiDirectionalAssociation.
private void handleBiDirectionalAssociation(CtClass managedCtClass, CtField persistentField, CtMethod fieldWriter) throws NotFoundException, CannotCompileException {
if (!PersistentAttributesHelper.isPossibleBiDirectionalAssociation(persistentField)) {
return;
}
final CtClass targetEntity = PersistentAttributesHelper.getTargetEntityClass(managedCtClass, persistentField);
if (targetEntity == null) {
log.infof("Could not find type of bi-directional association for field [%s#%s]", managedCtClass.getName(), persistentField.getName());
return;
}
final String mappedBy = PersistentAttributesHelper.getMappedBy(persistentField, targetEntity, enhancementContext);
if (mappedBy == null || mappedBy.isEmpty()) {
log.infof("Could not find bi-directional association for field [%s#%s]", managedCtClass.getName(), persistentField.getName());
return;
}
// create a temporary getter and setter on the target entity to be able to compile our code
final String mappedByGetterName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + mappedBy;
final String mappedBySetterName = EnhancerConstants.PERSISTENT_FIELD_WRITER_PREFIX + mappedBy;
CtMethod getter;
CtMethod setter;
boolean tmpTargetMethods = false;
try {
getter = targetEntity.getDeclaredMethod(mappedByGetterName);
setter = targetEntity.getDeclaredMethod(mappedByGetterName);
} catch (NotFoundException nfe) {
getter = MethodWriter.addGetter(targetEntity, mappedBy, mappedByGetterName);
setter = MethodWriter.addSetter(targetEntity, mappedBy, mappedBySetterName);
tmpTargetMethods = true;
}
// code fragments to check loaded state. We don't want to trigger lazy loading in association management code
String currentAssociationLoaded = String.format("%s.isPropertyInitialized(this.%s, \"%s\")", Hibernate.class.getName(), persistentField.getName(), mappedBy);
String targetElementLoaded = String.format("%s.isPropertyInitialized(target, \"%s\")", Hibernate.class.getName(), mappedBy);
String newAssociationLoaded = String.format("%s.isPropertyInitialized($1, \"%s\")", Hibernate.class.getName(), mappedBy);
if (PersistentAttributesHelper.hasAnnotation(persistentField, OneToOne.class)) {
// only unset when $1 != null to avoid recursion
fieldWriter.insertBefore(String.format(" if (this.%1$s != null && %2$s && $1 != null) { this.%1$s.%3$s(null); }%n", persistentField.getName(), currentAssociationLoaded, mappedBySetterName));
fieldWriter.insertAfter(String.format(" if ($1 != null && %s && $1.%s() != this) { $1.%s(this); }%n", newAssociationLoaded, mappedByGetterName, mappedBySetterName));
}
if (PersistentAttributesHelper.hasAnnotation(persistentField, OneToMany.class)) {
boolean isMap = PersistentAttributesHelper.isAssignable(persistentField.getType(), Map.class.getName());
String toArrayMethod = isMap ? "values().toArray()" : "toArray()";
// only remove elements not in the new collection or else we would loose those elements
// don't use iterator to avoid ConcurrentModException
fieldWriter.insertBefore(String.format(" if (this.%3$s != null && %1$s) {%n" + " Object[] array = this.%3$s.%2$s;%n" + " for (int i = 0; i < array.length; i++) {%n" + " %4$s target = (%4$s) array[i];%n" + " if ($1 == null || !$1.contains(target)) { target.%5$s(null); }%n" + " }%n" + " }%n", currentAssociationLoaded, toArrayMethod, persistentField.getName(), targetEntity.getName(), mappedBySetterName));
fieldWriter.insertAfter(String.format(" if ($1 != null && %1$s) {%n" + " Object[] array = $1.%2$s;%n" + " for (int i = 0; i < array.length; i++) {%n" + " %4$s target = (%4$s) array[i];%n" + " if (%3$s && target.%5$s() != this) { target.%6$s(this); }%n" + " }%n" + " }%n", newAssociationLoaded, toArrayMethod, targetElementLoaded, targetEntity.getName(), mappedByGetterName, mappedBySetterName));
}
if (PersistentAttributesHelper.hasAnnotation(persistentField, ManyToOne.class)) {
fieldWriter.insertBefore(String.format(" if (this.%2$s != null && %1$s && this.%2$s.%3$s() != null) { this.%2$s.%3$s().remove(this); }%n", currentAssociationLoaded, persistentField.getName(), mappedByGetterName));
// check .contains(this) to avoid double inserts (but preventing duplicates)
fieldWriter.insertAfter(String.format(" if ($1 != null && %s) {%n" + " java.util.Collection c = $1.%s();%n" + " if (c != null && !c.contains(this)) { c.add(this); }%n" + " }%n", newAssociationLoaded, mappedByGetterName));
}
if (PersistentAttributesHelper.hasAnnotation(persistentField, ManyToMany.class)) {
if (PersistentAttributesHelper.isAssignable(persistentField.getType(), Map.class.getName()) || PersistentAttributesHelper.isAssignable(targetEntity.getField(mappedBy).getType(), Map.class.getName())) {
log.infof("Bi-directional association for field [%s#%s] not managed: @ManyToMany in java.util.Map attribute not supported ", managedCtClass.getName(), persistentField.getName());
return;
}
fieldWriter.insertBefore(String.format(" if (this.%2$s != null && %1$s) {%n" + " Object[] array = this.%2$s.toArray();%n" + " for (int i = 0; i < array.length; i++) {%n" + " %3$s target = (%3$s) array[i];%n" + " if ($1 == null || !$1.contains(target)) { target.%4$s().remove(this); }%n" + " }%n" + " }%n", currentAssociationLoaded, persistentField.getName(), targetEntity.getName(), mappedByGetterName));
fieldWriter.insertAfter(String.format(" if ($1 != null && %s) {%n" + " Object[] array = $1.toArray();%n" + " for (int i = 0; i < array.length; i++) {%n" + " %s target = (%s) array[i];%n" + " if (%s) {%n" + " java.util.Collection c = target.%s();%n" + " if (c != this && c != null) { c.add(this); }%n" + " }%n" + " }%n" + " }%n", newAssociationLoaded, targetEntity.getName(), targetEntity.getName(), targetElementLoaded, mappedByGetterName));
}
if (tmpTargetMethods) {
targetEntity.removeMethod(getter);
targetEntity.removeMethod(setter);
}
}
use of javassist.CtMethod in project hibernate-orm by hibernate.
the class PersistentAttributesHelper method getterOrNull.
private static CtMethod getterOrNull(CtClass containerClass, String propertyName) {
for (CtMethod method : containerClass.getDeclaredMethods()) {
try {
// if the method has parameters, skip it
if (method.isEmpty() || method.getParameterTypes().length != 0) {
continue;
}
} catch (NotFoundException e) {
continue;
}
final String methodName = method.getName();
// try "get"
if (methodName.startsWith("get")) {
String testStdMethod = Introspector.decapitalize(methodName.substring(3));
String testOldMethod = methodName.substring(3);
if (testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName)) {
return method;
}
}
// if not "get", then try "is"
if (methodName.startsWith("is")) {
String testStdMethod = Introspector.decapitalize(methodName.substring(2));
String testOldMethod = methodName.substring(2);
if (testStdMethod.equals(propertyName) || testOldMethod.equals(propertyName)) {
return method;
}
}
}
return null;
}
use of javassist.CtMethod in project yyl_example by Relucent.
the class CreateSimpleBeanTest method create.
@SuppressWarnings("unchecked")
public static Class<? extends SimpleBean> create(String className, String... fields) throws CannotCompileException, NotFoundException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
cc.setInterfaces(new CtClass[] { pool.get(SimpleBean.class.getName()) });
CtClass stringctClass = pool.get("java.lang.String");
{
for (String field : fields) {
cc.addField(new CtField(stringctClass, field, cc));
}
}
{
CtMethod setCtMethod = new CtMethod(CtClass.voidType, "set", new CtClass[] { stringctClass, stringctClass }, cc);
setCtMethod.setModifiers(Modifier.PUBLIC);
StringBuilder vSetBody = new StringBuilder();
vSetBody.append("if(null == $1){ throw new NullPointerException(\" key can not be NULL \"); }");
for (String field : fields) {
vSetBody.append("else if(\"").append(field).append("\".equals($1)){ $0.").append(field).append("=$2; }");
}
vSetBody.append("else { throw new IllegalArgumentException(\"Object does not exist in the \" + $1 + \" field\"); }");
setCtMethod.setBody(vSetBody.toString());
cc.addMethod(setCtMethod);
}
{
CtMethod getCtMethod = new CtMethod(stringctClass, "get", new CtClass[] { stringctClass }, cc);
getCtMethod.setModifiers(Modifier.PUBLIC);
StringBuilder vGetBody = new StringBuilder();
vGetBody.append("if(null == $1){ throw new NullPointerException(\" key can not be NULL \"); }");
for (String field : fields) {
vGetBody.append("else if(\"").append(field).append("\".equals($1)){ return $0.").append(field).append("; }");
}
vGetBody.append("else { throw new IllegalArgumentException(\"Object does not exist in the \" + $1 + \" field\"); }");
getCtMethod.setBody(vGetBody.toString());
cc.addMethod(getCtMethod);
}
{
CtConstructor cons = new CtConstructor(new CtClass[] {}, cc);
cons.setBody("{}");
cc.addConstructor(cons);
}
cc.detach();
return cc.toClass();
}
use of javassist.CtMethod in project java-chassis by ServiceComb.
the class JavassistUtils method addEnumValuesMethod.
private static void addEnumValuesMethod(CtClass ctClass, List<String> values) throws CannotCompileException {
StringBuilder sb = new StringBuilder();
sb.append("public static Enum[] values(){return new Enum[]{");
for (int idx = 0; idx < values.size(); idx++) {
String value = values.get(idx);
String line = String.format("new %s(\"%s\", %d),", ctClass.getName(), value, idx);
sb.append(line);
}
sb.setLength(sb.length() - 1);
sb.append("};}");
CtMethod valuesMethod = CtMethod.make(sb.toString(), ctClass);
ctClass.addMethod(valuesMethod);
}
use of javassist.CtMethod in project java-chassis by ServiceComb.
the class JavassistUtils method createClass.
public static Class<?> createClass(ClassLoader classLoader, ClassConfig config) {
if (classLoader == null) {
classLoader = Thread.currentThread().getContextClassLoader();
}
appendThreadClassPath();
CtClass ctClass = null;
if (config.isIntf()) {
ctClass = POOL.makeInterface(config.getClassName());
} else {
ctClass = POOL.makeClass(config.getClassName());
}
try {
for (String intfName : config.getIntfList()) {
ctClass.addInterface(POOL.get(intfName));
}
for (FieldConfig fieldConfig : config.getFieldList()) {
CtField field = createCtField(POOL, ctClass, fieldConfig);
ctClass.addField(field);
}
for (MethodConfig methodConfig : config.getMethodList()) {
CtMethod ctMethod = CtMethod.make(methodConfig.getSource(), ctClass);
if (methodConfig.getGenericSignature() != null) {
ctMethod.setGenericSignature(methodConfig.getGenericSignature());
}
ctClass.addMethod(ctMethod);
}
return ctClass.toClass(classLoader, null);
} catch (Throwable e) {
throw new Error(e);
}
}
Aggregations