gt:         return getClassName().replace('.', '/');
context: /*******************************************************************************
   * Copyright (c) 2014, 2015  Oracle and/or its affiliates. All rights reserved.
   * This program and the accompanying materials are made available under the
   * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
   * which accompanies this distribution.
   * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
   * and the Eclipse Distribution License is available at
   * http://www.eclipse.org/org/documents/edl-v10.php.
   *
   * Contributors:
   *     Dmitry Kornilov - Initial implementation
   ******************************************************************************/
  package org.eclipse.persistence.internal.jpa.weaving;
  
  import org.eclipse.persistence.dynamic.DynamicClassLoader;
  import org.eclipse.persistence.dynamic.EclipseLinkClassWriter;
  import org.eclipse.persistence.internal.libraries.asm.ClassWriter;
  import org.eclipse.persistence.internal.libraries.asm.FieldVisitor;
  import org.eclipse.persistence.internal.libraries.asm.Label;
  import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
  import org.eclipse.persistence.internal.libraries.asm.Opcodes;
  
  /**
   * Generates a subclass of given collection implementing CollectionProxy interface.
   * {@see CollectionProxy}
   *
   * @author Dmitry Kornilov
   * @since EclipseLink 2.6.0
   */
  public class CollectionProxyClassWriter implements EclipseLinkClassWriter, Opcodes {
      private static final String CLASS_NAME_SUFFIX = "CollectionProxy";
      private static final String INTERFACE = "org/eclipse/persistence/jpa/rs/util/CollectionProxy";
  
      private final String parentClassName;
      private final String entityName;
      private final String fieldName;
  
      /**
       * Creates a new CollectionProxyClassWriter for the given attribute of the given entity of given type.
       *
       * @param parentClassName the superclass name.
       * @param entityName entity name
       * @param fieldName entity attribute name
       */
      public CollectionProxyClassWriter(String parentClassName, String entityName, String fieldName) {
          this.parentClassName = parentClassName;
          this.entityName = entityName;
          this.fieldName = fieldName;
      }
  
      /**
       * Returns a class name for CollectionProxy based on parent class name and field name
       * to generate proxy for.
       * The name is constructed as _<className>_<fieldName>_RestCollectionProxy.
       *
       * @param entityName full class name (including package)
       * @param fieldName field name
       * @return Rest collection proxy name.
       */
      public static String getClassName(String entityName, String fieldName) {
          final int index = entityName.lastIndexOf('.');
          final String packageName = index >= 0 ? entityName.substring(0, index) : "";
          final String shortClassName = index >= 0 ? entityName.substring(index + 1) : entityName;
          return packageName + "._" + shortClassName + "_" + fieldName + "_" + CLASS_NAME_SUFFIX;
      }
  
      /**
       * Returns a class name for generated CollectionProxy.
       * {@see CollectionProxyClassWriter#getClassName(String, String)}
       *
       * @return Rest collection proxy name.
       */
      public String getClassName() {
          return getClassName(entityName, fieldName);
      }
  
      /**
       *  public class Proxy extends SuperType implements CollectionProxy {
       *      private List<LinkV2> links;
       *
       *      public CollectionProxy(Collection c) {
       *          super();
       *          this.addAll(c);
       *      }
       *
       *      @Override
       *      public List<LinkV2> getLinks() {
       *          return links;
       *      }
       *
       *      @Override
       *      public void setLinks(List<LinkV2> links) {
       *          this.links = links;
       *      }
       *  }
       *
       * @param loader
       * @param className
       * @return
       * @throws Exception
       */
      @Override
      public byte[] writeClass(DynamicClassLoader loader, String className) {
  
          final ClassWriter cw = new ClassWriter(0);
          MethodVisitor mv;
  
          // public class Proxy extends SuperType implements CollectionProxy
          cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, getASMClassName(), null, getASMParentClassName(), new String[]{INTERFACE});
  
          // private List<LinkV2> links;
          final FieldVisitor fv = cw.visitField(ACC_PRIVATE, "links", "Ljava/util/List;", "Ljava/util/List<Lorg/eclipse/persistence/internal/jpa/rs/metadata/model/LinkV2;>;", null);
          fv.visitEnd();
  
          // public CollectionProxy(Collection c) {
          //     super();
          //     this.addAll(c);
          // }
          {
              mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(Ljava/util/Collection;)V", null, null);
              mv.visitCode();
              Label l0 = new Label();
              mv.visitLabel(l0);
              mv.visitLineNumber(15, l0);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitMethodInsn(INVOKESPECIAL, getASMParentClassName(), "<init>", "()V", false);
              Label l1 = new Label();
              mv.visitLabel(l1);
              mv.visitLineNumber(16, l1);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitVarInsn(ALOAD, 1);
              mv.visitMethodInsn(INVOKEVIRTUAL, getASMClassName(), "addAll", "(Ljava/util/Collection;)Z", false);
              mv.visitInsn(POP);
              Label l2 = new Label();
              mv.visitLabel(l2);
              mv.visitLineNumber(17, l2);
              mv.visitInsn(RETURN);
              Label l3 = new Label();
              mv.visitLabel(l3);
              mv.visitLocalVariable("this", "L" + getASMClassName() + ";", null, l0, l3, 0);
              mv.visitLocalVariable("c", "Ljava/util/Collection;", null, l0, l3, 1);
              mv.visitMaxs(2, 2);
              mv.visitEnd();
          }
  
          // @Override
          // public List<LinkV2> getLinks() {
          //    return links;
          // }
          {
              mv = cw.visitMethod(ACC_PUBLIC, "getLinks", "()Ljava/util/List;", "()Ljava/util/List<Lorg/eclipse/persistence/internal/jpa/rs/metadata/model/LinkV2;>;", null);
              mv.visitCode();
              Label l0 = new Label();
              mv.visitLabel(l0);
              mv.visitLineNumber(21, l0);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitFieldInsn(GETFIELD, getASMClassName(), "links", "Ljava/util/List;");
              mv.visitInsn(ARETURN);
              Label l1 = new Label();
              mv.visitLabel(l1);
              mv.visitLocalVariable("this", "L" + getASMClassName() + ";", null, l0, l1, 0);
              mv.visitMaxs(1, 1);
              mv.visitEnd();
          }
  
          // @Override
          // public void setLinks(List<LinkV2> links) {
          //    this.links = links;
          // }
          {
              mv = cw.visitMethod(ACC_PUBLIC, "setLinks", "(Ljava/util/List;)V", "(Ljava/util/List<Lorg/eclipse/persistence/internal/jpa/rs/metadata/model/LinkV2;>;)V", null);
              mv.visitCode();
              Label l0 = new Label();
              mv.visitLabel(l0);
              mv.visitLineNumber(26, l0);
              mv.visitVarInsn(ALOAD, 0);
              mv.visitVarInsn(ALOAD, 1);
              mv.visitFieldInsn(PUTFIELD, getASMClassName(), "links", "Ljava/util/List;");
              Label l1 = new Label();
              mv.visitLabel(l1);
              mv.visitLineNumber(27, l1);
              mv.visitInsn(RETURN);
              Label l2 = new Label();
              mv.visitLabel(l2);
              mv.visitLocalVariable("this", "L" + getASMClassName()+ ";", null, l0, l2, 0);
              mv.visitLocalVariable("links", "Ljava/util/List;", "Ljava/util/List<Lorg/eclipse/persistence/internal/jpa/rs/metadata/model/LinkV2;>;", l0, l2, 1);
              mv.visitMaxs(2, 2);
              mv.visitEnd();
          }
  
          return cw.toByteArray();
      }
  
      @Override
      public boolean isCompatible(EclipseLinkClassWriter writer) {
          return getParentClassName().equals(writer.getParentClassName());
      }
  
      @Override
      public Class<?> getParentClass() {
          return null;
      }
  
      @Override
      public String getParentClassName() {
          return parentClassName;
      }
  
      private String getASMClassName() {
  