コード例 #1
0
  private CtMethod generateFieldReader(
      CtClass managedCtClass, CtField persistentField, AttributeTypeDescriptor typeDescriptor) {
    final String fieldName = persistentField.getName();
    final String readerName = EnhancerConstants.PERSISTENT_FIELD_READER_PREFIX + fieldName;

    // read attempts only have to deal lazy-loading support, not dirty checking;
    // so if the field is not enabled as lazy-loadable return a plain simple getter as the reader
    if (!enhancementContext.isLazyLoadable(persistentField)) {
      return MethodWriter.addGetter(managedCtClass, fieldName, readerName);
    }

    try {
      return MethodWriter.write(
          managedCtClass,
          "public %s %s() {%n  %s%n  return this.%s;%n}",
          persistentField.getType().getName(),
          readerName,
          typeDescriptor.buildReadInterceptionBodyFragment(fieldName),
          fieldName);
    } catch (CannotCompileException cce) {
      final String msg =
          String.format(
              "Could not enhance entity class [%s] to add field reader method [%s]",
              managedCtClass.getName(), readerName);
      throw new EnhancementException(msg, cce);
    } catch (NotFoundException nfe) {
      final String msg =
          String.format(
              "Could not enhance entity class [%s] to add field reader method [%s]",
              managedCtClass.getName(), readerName);
      throw new EnhancementException(msg, nfe);
    }
  }
コード例 #2
0
  private void handleBiDirectionalAssociation(
      CtClass managedCtClass, CtField persistentField, CtMethod fieldWriter)
      throws NotFoundException, CannotCompileException {
    if (!isPossibleBiDirectionalAssociation(persistentField)) {
      return;
    }
    final CtClass targetEntity = getTargetEntityClass(persistentField);
    if (targetEntity == null) {
      log.debugf(
          "Could not find type of bi-directional association for field [%s#%s]",
          managedCtClass.getName(), persistentField.getName());
      return;
    }
    final String mappedBy = getMappedBy(persistentField, targetEntity);
    if (mappedBy.isEmpty()) {
      log.warnf(
          "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;
    MethodWriter.addGetter(targetEntity, mappedBy, mappedByGetterName);
    MethodWriter.addSetter(targetEntity, mappedBy, mappedBySetterName);

    if (persistentField.hasAnnotation(OneToOne.class)) {
      // only unset when $1 != null to avoid recursion
      fieldWriter.insertBefore(
          String.format(
              "if ($0.%s != null && $1 != null) $0.%<s.%s(null);%n",
              persistentField.getName(), mappedBySetterName));
      fieldWriter.insertAfter(
          String.format(
              "if ($1 != null && $1.%s() != $0) $1.%s($0);%n",
              mappedByGetterName, mappedBySetterName));
    }
    if (persistentField.hasAnnotation(OneToMany.class)) {
      // 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 ($0.%s != null) { Object[] array = $0.%<s.toArray(); for (int i = 0; i < array.length; i++) { %s target = (%<s) array[i]; if ($1 == null || !$1.contains(target)) target.%s(null); } }%n",
              persistentField.getName(), targetEntity.getName(), mappedBySetterName));
      fieldWriter.insertAfter(
          String.format(
              "if ($1 != null) { Object[] array = $1.toArray(); for (int i = 0; i < array.length; i++) { %s target = (%<s) array[i]; if (target.%s() != $0) target.%s((%s)$0); } }%n",
              targetEntity.getName(),
              mappedByGetterName,
              mappedBySetterName,
              managedCtClass.getName()));
    }
    if (persistentField.hasAnnotation(ManyToOne.class)) {
      fieldWriter.insertBefore(
          String.format(
              "if ($0.%1$s != null && $0.%1$s.%2$s() != null) $0.%1$s.%2$s().remove($0);%n",
              persistentField.getName(), mappedByGetterName));
      // check .contains($0) to avoid double inserts (but preventing duplicates)
      fieldWriter.insertAfter(
          String.format(
              "if ($1 != null) { java.util.Collection c = $1.%s(); if (c != null && !c.contains($0)) c.add($0); }%n",
              mappedByGetterName));
    }
    if (persistentField.hasAnnotation(ManyToMany.class)) {
      fieldWriter.insertBefore(
          String.format(
              "if ($0.%s != null) { Object[] array = $0.%<s.toArray(); for (int i = 0; i < array.length; i++) { %s target = (%<s) array[i]; if ($1 == null || !$1.contains(target)) target.%s().remove($0); } }%n",
              persistentField.getName(), targetEntity.getName(), mappedByGetterName));
      fieldWriter.insertAfter(
          String.format(
              "if ($1 != null) { Object[] array = $1.toArray(); for (int i = 0; i < array.length; i++) { %s target = (%<s) array[i]; java.util.Collection c = target.%s(); if ( c != $0 && c != null) c.add($0); } }%n",
              targetEntity.getName(), mappedByGetterName));
    }
    // implementation note: association management @OneToMany and @ManyToMay works for add()
    // operations but for remove() a snapshot of the collection is needed so we know what
    // associations to break.
    // another approach that could force that behavior would be to return
    // Collections.unmodifiableCollection() ...
  }