View Javadoc

1   /*
2    * Entreri, an entity-component framework in Java
3    *
4    * Copyright (c) 2013, Michael Ludwig
5    * All rights reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without modification,
8    * are permitted provided that the following conditions are met:
9    *
10   *     Redistributions of source code must retain the above copyright notice,
11   *         this list of conditions and the following disclaimer.
12   *     Redistributions in binary form must reproduce the above copyright notice,
13   *         this list of conditions and the following disclaimer in the
14   *         documentation and/or other materials provided with the distribution.
15   *
16   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
20   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   */
27  package com.lhkbob.entreri.impl;
28  
29  import com.lhkbob.entreri.Component;
30  
31  import javax.annotation.processing.ProcessingEnvironment;
32  import javax.lang.model.element.TypeElement;
33  import java.util.List;
34  
35  /**
36   * ComponentSpecification provides an interface to access the information encoded in a
37   * Component sub-interface in order to generate a proxy implementation. The specification
38   * can be extracted at runtime using reflection, or at compile time using the annotation
39   * processor mirror API. The two factory methods, {@link Factory#fromClass(Class)} and
40   * {@link Factory#fromTypeElement(javax.lang.model.element.TypeElement,
41   * javax.annotation.processing.ProcessingEnvironment)} correspond to these two scenarios.
42   *
43   * @author Michael Ludwig
44   */
45  public interface ComponentSpecification {
46      /**
47       * Get the qualified name of the component type, with the package prefix removed.
48       * Thus, the returned string should be valid to insert into source code within the
49       * same package of the component and refer to that exact type.
50       *
51       * @return The component type
52       */
53      public String getType();
54  
55      /**
56       * @return The package the component type resides in
57       */
58      public String getPackage();
59  
60      /**
61       * Get all properties that must be implemented for this component type. This will
62       * include all properties defined in a parent component type if the type does not
63       * directly extend Component.
64       * <p/>
65       * The returned list will be immutable and sorted by logical property name.
66       *
67       * @return The list of all properties for the component
68       */
69      public List<? extends PropertyDeclaration> getProperties();
70  
71      public static final class Factory {
72          private Factory() {
73          }
74  
75          /**
76           * Produce a ComponentSpecification for the given Component class type.
77           *
78           * @param type The component type
79           *
80           * @return The extracted ComponentSpecification
81           *
82           * @throws com.lhkbob.entreri.IllegalComponentDefinitionException
83           *          if the class does not follow the specification defined in Component,
84           *          or if referenced Property classes do not meet their requirements
85           */
86          public static ComponentSpecification fromClass(Class<? extends Component> type) {
87              return new ReflectionComponentSpecification(type);
88          }
89  
90          /**
91           * Produce a ComponentSpecification for the given Component type element, within
92           * the context of the ProcessingEnvironment used by the active annotation
93           * processor. The returned specification maintains no dependencies to the
94           * processing environment but no guarantee is made on its validity after the
95           * processing round completes.
96           *
97           * @param type The component type
98           * @param env  The ProcessingEnvironment for the current round
99           *
100          * @return The extracted ComponentSpecification
101          *
102          * @throws com.lhkbob.entreri.IllegalComponentDefinitionException
103          *          if the class does not follow the specification defined in Component,
104          *          or if referenced Property classes do not meet ther requirements
105          */
106         public static ComponentSpecification fromTypeElement(TypeElement type,
107                                                              ProcessingEnvironment env) {
108             return new MirrorComponentSpecification(type, env.getTypeUtils(),
109                                                     env.getElementUtils(),
110                                                     env.getFiler());
111         }
112     }
113 }