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 }