1 /*
   2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * Use is subject to the license terms.
  28  */
  29 package com.sun.tools.internal.xjc.generator.bean;
  30 
  31 import javax.xml.bind.annotation.XmlAccessType;
  32 import javax.xml.bind.annotation.XmlEnum;
  33 import javax.xml.bind.annotation.XmlEnumValue;
  34 
  35 import com.sun.codemodel.internal.JClassContainer;
  36 import com.sun.codemodel.internal.JDefinedClass;
  37 import com.sun.codemodel.internal.JDocComment;
  38 import com.sun.codemodel.internal.JMethod;
  39 import com.sun.codemodel.internal.JMod;
  40 import com.sun.codemodel.internal.JPackage;
  41 import com.sun.codemodel.internal.JType;
  42 import com.sun.codemodel.internal.JVar;
  43 import com.sun.tools.internal.xjc.generator.annotation.spec.XmlAccessorTypeWriter;
  44 import com.sun.tools.internal.xjc.model.CClassInfo;
  45 import com.sun.tools.internal.xjc.outline.Aspect;
  46 import com.sun.tools.internal.xjc.outline.Outline;
  47 
  48 /**
  49  * Decides how a bean token is mapped to the generated classes.
  50  *
  51  * <p>
  52  * The actual implementations of this interface is tightly coupled with
  53  * the backend, but the front-end gets to choose which strategy to be used.
  54  *
  55  * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
  56  */
  57 @XmlEnum(Boolean.class)
  58 public enum ImplStructureStrategy {
  59     /**
  60      * Generates beans only. The simplest code generation.
  61      */
  62     @XmlEnumValue("true")
  63     BEAN_ONLY() {
  64         protected Result createClasses(Outline outline, CClassInfo bean) {
  65             JClassContainer parent = outline.getContainer( bean.parent(), Aspect.EXPOSED );
  66 
  67             JDefinedClass impl = outline.getClassFactory().createClass(
  68                 parent,
  69                 JMod.PUBLIC|(parent.isPackage()?0:JMod.STATIC)|(bean.isAbstract()?JMod.ABSTRACT:0),
  70                 bean.shortName, bean.getLocator() );
  71             impl.annotate2(XmlAccessorTypeWriter.class).value(XmlAccessType.FIELD);
  72 
  73             return new Result(impl,impl);
  74         }
  75 
  76         protected JPackage getPackage(JPackage pkg, Aspect a) {
  77             return pkg;
  78         }
  79 
  80         protected MethodWriter createMethodWriter(final ClassOutlineImpl target) {
  81             assert target.ref==target.implClass;
  82 
  83             return new MethodWriter(target) {
  84                 private final JDefinedClass impl = target.implClass;
  85 
  86                 private JMethod implMethod;
  87 
  88                 public JVar addParameter(JType type, String name) {
  89                     return implMethod.param(type,name);
  90                 }
  91 
  92                 public JMethod declareMethod(JType returnType, String methodName) {
  93                     implMethod = impl.method( JMod.PUBLIC, returnType, methodName );
  94                     return implMethod;
  95                 }
  96 
  97                 public JDocComment javadoc() {
  98                     return implMethod.javadoc();
  99                 }
 100             };
 101         }
 102 
 103         protected void _extends(ClassOutlineImpl derived, ClassOutlineImpl base) {
 104             derived.implClass._extends(base.implRef);
 105         }
 106     },
 107 
 108     /**
 109      * Generates the interfaces to describe beans (content interfaces)
 110      * and then the beans themselves in a hidden impl package.
 111      *
 112      * Similar to JAXB 1.0.
 113      */
 114     @XmlEnumValue("false")
 115     INTF_AND_IMPL() {
 116         protected Result createClasses( Outline outline, CClassInfo bean ) {
 117             JClassContainer parent = outline.getContainer( bean.parent(), Aspect.EXPOSED );
 118 
 119             JDefinedClass intf = outline.getClassFactory().createInterface(
 120                 parent, bean.shortName, bean.getLocator() );
 121 
 122             parent = outline.getContainer(bean.parent(), Aspect.IMPLEMENTATION);
 123             JDefinedClass impl = outline.getClassFactory().createClass(
 124                 parent,
 125                 JMod.PUBLIC|(parent.isPackage()?0:JMod.STATIC)|(bean.isAbstract()?JMod.ABSTRACT:0),
 126                 bean.shortName+"Impl", bean.getLocator() );
 127             impl.annotate2(XmlAccessorTypeWriter.class).value(XmlAccessType.FIELD);
 128 
 129             impl._implements(intf);
 130 
 131             return new Result(intf,impl);
 132         }
 133 
 134         protected JPackage getPackage(JPackage pkg, Aspect a) {
 135             switch(a) {
 136             case EXPOSED:
 137                 return pkg;
 138             case IMPLEMENTATION:
 139                 return pkg.subPackage("impl");
 140             default:
 141                 assert false;
 142                 throw new IllegalStateException();
 143             }
 144         }
 145 
 146         protected MethodWriter createMethodWriter(final ClassOutlineImpl target) {
 147             return new MethodWriter(target) {
 148                 private final JDefinedClass intf = target.ref;
 149                 private final JDefinedClass impl = target.implClass;
 150 
 151                 private JMethod intfMethod;
 152                 private JMethod implMethod;
 153 
 154                 public JVar addParameter(JType type, String name) {
 155                     // TODO: do we still need to deal with the case where intf is null?
 156                     if(intf!=null)
 157                         intfMethod.param(type,name);
 158                     return implMethod.param(type,name);
 159                 }
 160 
 161                 public JMethod declareMethod(JType returnType, String methodName) {
 162                     if(intf!=null)
 163                         intfMethod = intf.method( 0, returnType, methodName );
 164                     implMethod = impl.method( JMod.PUBLIC, returnType, methodName );
 165                     return implMethod;
 166                 }
 167 
 168                 public JDocComment javadoc() {
 169                     if(intf!=null)
 170                         return intfMethod.javadoc();
 171                     else
 172                         return implMethod.javadoc();
 173                 }
 174             };
 175         }
 176 
 177         protected void _extends(ClassOutlineImpl derived, ClassOutlineImpl base) {
 178             derived.implClass._extends(base.implRef);
 179             derived.ref._implements(base.ref);
 180         }
 181     };
 182 
 183 
 184     /**
 185      * Creates class(es) for the given bean.
 186      */
 187     protected abstract Result createClasses( Outline outline, CClassInfo bean );
 188 
 189     /**
 190      * Gets the specified aspect of the given package.
 191      */
 192     protected abstract JPackage getPackage( JPackage pkg, Aspect a );
 193 
 194     protected abstract MethodWriter createMethodWriter( ClassOutlineImpl target );
 195 
 196     /**
 197      * Sets up an inheritance relationship.
 198      */
 199     protected abstract void _extends( ClassOutlineImpl derived, ClassOutlineImpl base );
 200 
 201     public static final class Result {
 202         /**
 203          * Corresponds to {@link Aspect#EXPOSED}
 204          */
 205         public final JDefinedClass exposed;
 206         /**
 207          * Corresponds to {@link Aspect#IMPLEMENTATION}
 208          */
 209         public final JDefinedClass implementation;
 210 
 211         public Result(JDefinedClass exposed, JDefinedClass implementation) {
 212             this.exposed = exposed;
 213             this.implementation = implementation;
 214         }
 215     }
 216 }