Skip to content

Commit 13753fe

Browse files
committed
CDK: refactored, some tests
1 parent 5b27b32 commit 13753fe

File tree

5 files changed

+63
-20
lines changed

5 files changed

+63
-20
lines changed

primefaces-cdk/primefaces-cdk-api/src/main/java/org/primefaces/cdk/api/PrimePropertyKeys.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,5 +103,13 @@ public interface PrimePropertyKeys {
103103
*/
104104
String getImplicitDefaultValue();
105105

106+
/**
107+
* Whether this property is hidden from the generated taglib.
108+
*
109+
* <p>Hidden properties are still fully generated (getter, setter, StateHelper entry),
110+
* but are excluded from taglib output.</p>
111+
*
112+
* @return true if the property should be omitted from the taglib, false otherwise
113+
*/
106114
boolean isHidden();
107115
}

primefaces-cdk/primefaces-cdk-api/src/main/java/org/primefaces/cdk/api/Property.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,24 @@
9595
*/
9696
boolean callSuper() default false;
9797

98+
/**
99+
* Manually overrides the property type used in taglib generation.
100+
*
101+
* <p>For Components and Behaviors the type is automatically extracted from the getter
102+
* return type and this attribute can be left at its default. For TagHandlers, where no
103+
* getter return type is available, the type must be specified explicitly.</p>
104+
*
105+
* @return the explicit property type, or {@code Object.class} to use the inferred type
106+
*/
98107
Class<?> type() default Object.class;
99108

109+
/**
110+
* Whether this property should be omitted from the generated taglib.
111+
*
112+
* <p>Hidden properties are still fully generated (getter, setter, StateHelper entry),
113+
* but are excluded from taglib output.</p>
114+
*
115+
* @return true if the property should be omitted from the taglib, false otherwise
116+
*/
100117
boolean hide() default false;
101118
}

primefaces-cdk/primefaces-cdk-impl/src/main/java/org/primefaces/cdk/impl/container/PropertyInfo.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public PropertyInfo(String name, Property annotation, ExecutableElement getterEl
4242
this.annotation = annotation;
4343
this.getterElement = getterElement;
4444
this.setterElement = setterElement;
45-
this.generateGetter = true;
46-
this.generateSetter = true;
45+
this.generateGetter = false;
46+
this.generateSetter = false;
4747
this.typeName = typeName;
4848
}
4949

@@ -52,8 +52,6 @@ public PropertyInfo(String name, Property annotation) {
5252
this.annotation = annotation;
5353
this.getterElement = null;
5454
this.setterElement = null;
55-
// in this case, this is an extracted property from a parent component without @Property annotation
56-
// -> skip generation
5755
this.generateGetter = false;
5856
this.generateSetter = false;
5957
this.typeName = null;

primefaces-cdk/primefaces-cdk-impl/src/main/java/org/primefaces/cdk/impl/subclass/AnnotationProcessor.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,21 +159,21 @@ private void generateComponent(TypeElement classElement) {
159159
// Inject synthetic "id" property for components (not behaviors) when absent.
160160
if (!isBehavior) {
161161
if (!propsMap.containsKey("id")) {
162-
Property property = new PropertyLiteral( "Unique identifier of the component in a namingContainer.",
162+
Property property = new PropertyLiteral("Unique identifier of the component in a namingContainer.",
163163
false,
164164
"",
165165
"generated", false, String.class, false);
166166
propsMap.put("id", new PropertyInfo("id", property));
167167
}
168168
if (!propsMap.containsKey("binding")) {
169-
Property property = new PropertyLiteral( "An EL expression referring to a server side UIComponent instance in a backing bean.",
169+
Property property = new PropertyLiteral("An EL expression referring to a server side UIComponent instance in a backing bean.",
170170
false,
171171
"",
172172
"generated", false, UIComponent.class, false);
173173
propsMap.put("binding", new PropertyInfo("binding", property));
174174
}
175175
if (!propsMap.containsKey("rendered")) {
176-
Property property = new PropertyLiteral( "Unique identifier of the component in a namingContainer.",
176+
Property property = new PropertyLiteral("Unique identifier of the component in a namingContainer.",
177177
false,
178178
"",
179179
"generated", false, Boolean.class, false);

primefaces-cdk/primefaces-cdk-impl/src/main/java/org/primefaces/cdk/impl/subclass/HierarchyScanner.java

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import java.util.ArrayDeque;
3838
import java.util.ArrayList;
39+
import java.util.Collections;
3940
import java.util.Deque;
4041
import java.util.HashSet;
4142
import java.util.LinkedHashMap;
@@ -50,6 +51,7 @@
5051
import javax.lang.model.element.Element;
5152
import javax.lang.model.element.ElementKind;
5253
import javax.lang.model.element.ExecutableElement;
54+
import javax.lang.model.element.Modifier;
5355
import javax.lang.model.element.TypeElement;
5456
import javax.lang.model.type.TypeMirror;
5557
import javax.tools.Diagnostic;
@@ -104,6 +106,19 @@ public HierarchyScannerResult scan(TypeElement root) {
104106
HierarchyScannerResult nodeResult = scanSingleNode(node);
105107

106108
for (PropertyInfo p : nodeResult.getProperties()) {
109+
// we need to generate getter/setter if not yet implemented
110+
if (node.getKind() == ElementKind.INTERFACE
111+
|| p.getGetterElement() == null
112+
|| p.getGetterElement().getModifiers().contains(Modifier.ABSTRACT)) {
113+
p.setGenerateGetter(true);
114+
}
115+
if (p.isGenerateGetter()
116+
|| node.getKind() == ElementKind.INTERFACE
117+
|| p.getSetterElement() == null
118+
|| p.getSetterElement().getModifiers().contains(Modifier.ABSTRACT)) {
119+
p.setGenerateSetter(true);
120+
}
121+
107122
PropertyInfo before = mergedProperties.get(p.getName());
108123
if (before != null) {
109124
// Back-fill blank metadata from the parent before the child wins.
@@ -120,6 +135,7 @@ public HierarchyScannerResult scan(TypeElement root) {
120135
p.getAnnotation().hide()));
121136
}
122137
}
138+
123139
mergedProperties.put(p.getName(), p);
124140
}
125141

@@ -190,13 +206,11 @@ HierarchyScannerResult scanSingleNode(TypeElement element) {
190206
* Tries the {@code PropertyKeys} reflection strategy first, then the {@code @Property} annotation strategy.
191207
*/
192208
private List<PropertyInfo> scanProperties(TypeElement element) {
209+
List<PropertyInfo> result = new ArrayList<>();
193210
String className = element.getQualifiedName().toString();
194211
try {
195212
Class<?> clazz = Class.forName(className, false, processorClassLoader);
196-
List<PropertyInfo> reflectionResult = scanPropertyKeysViaReflection(clazz, element);
197-
if (reflectionResult != null) {
198-
return reflectionResult;
199-
}
213+
result.addAll(scanPropertyKeysViaReflection(clazz, element));
200214
}
201215
catch (ClassNotFoundException ignored) {
202216
// in-round source — fall through to annotation scan
@@ -205,7 +219,7 @@ private List<PropertyInfo> scanProperties(TypeElement element) {
205219
messager.printMessage(Diagnostic.Kind.WARNING,
206220
"Reflection failed for " + className + ": " + e.getMessage());
207221
}
208-
return scanPropertyAnnotations(element);
222+
return scanPropertyAnnotations(element, result);
209223
}
210224

211225
/**
@@ -254,7 +268,7 @@ private List<PropertyInfo> scanPropertyKeysViaReflection(Class<?> clazz, TypeEle
254268

255269
return result;
256270
}
257-
return null;
271+
return Collections.emptyList();
258272
}
259273

260274
/**
@@ -305,9 +319,7 @@ private ExecutableElement findGetterElement(TypeElement element, String property
305319
/**
306320
* Scans {@code @Property}-annotated getters via the Element API.
307321
*/
308-
private List<PropertyInfo> scanPropertyAnnotations(TypeElement element) {
309-
List<PropertyInfo> result = new ArrayList<>();
310-
322+
private List<PropertyInfo> scanPropertyAnnotations(TypeElement element, List<PropertyInfo> result) {
311323
for (Element enclosed : element.getEnclosedElements()) {
312324
if (enclosed.getKind() != ElementKind.METHOD) {
313325
continue;
@@ -327,10 +339,18 @@ private List<PropertyInfo> scanPropertyAnnotations(TypeElement element) {
327339

328340
String propName = extractPropertyName(methodName);
329341
ExecutableElement setter = findSetterInElement(element, propName, method.getReturnType());
330-
result.add(new PropertyInfo(propName,
331-
new PropertyLiteral(annotation.description(), annotation.required(), annotation.defaultValue(),
332-
annotation.implicitDefaultValue(), annotation.callSuper(), null, annotation.hide()),
333-
method, setter, method.getReturnType().toString()));
342+
PropertyInfo propertyInfo = result.stream().filter(p -> p.getName().equals(propName)).findFirst().orElse(null);
343+
if (propertyInfo == null) {
344+
result.add(new PropertyInfo(propName,
345+
new PropertyLiteral(annotation.description(), annotation.required(), annotation.defaultValue(),
346+
annotation.implicitDefaultValue(), annotation.callSuper(), null, annotation.hide()),
347+
method, setter, method.getReturnType().toString()));
348+
}
349+
else {
350+
propertyInfo.setGetterElement(method);
351+
propertyInfo.setSetterElement(setter);
352+
propertyInfo.setTypeName(method.getReturnType().toString());
353+
}
334354
}
335355

336356
return result;

0 commit comments

Comments
 (0)