use of org.jooq.tools.reflect.ReflectException in project jOOQ by jOOQ.
the class JavaGenerator method printClassAnnotations.
protected void printClassAnnotations(JavaWriter out, Definition definition, Mode mode) {
if (generateGeneratedAnnotation()) {
SchemaDefinition schema = definition.getSchema();
CatalogDefinition catalog = definition.getCatalog();
// [#7581] The concrete annotation type depends on the JDK, with
// javax.annotation.Generated being deprecated in JDK 9
GeneratedAnnotationType type = generateGeneratedAnnotationType();
if (type == null)
type = GeneratedAnnotationType.DETECT_FROM_JDK;
String generated;
switch(type) {
case DETECT_FROM_JDK:
try {
// Seems more reliable than tampering with java.version
Reflect.onClass("java.util.Optional").call("of", new Object()).call("stream");
generated = "javax.annotation.processing.Generated";
} catch (ReflectException e) {
generated = "javax.annotation.Generated";
}
break;
case JAVAX_ANNOTATION_GENERATED:
generated = "javax.annotation.Generated";
break;
case JAVAX_ANNOTATION_PROCESSING_GENERATED:
generated = "javax.annotation.processing.Generated";
break;
default:
throw new IllegalStateException("Unsupported type: " + type);
}
out.println("@%s(", out.ref(generated));
if (useSchemaVersionProvider() || useCatalogVersionProvider()) {
boolean hasCatalogVersion = !StringUtils.isBlank(catalogVersions.get(catalog));
boolean hasSchemaVersion = !StringUtils.isBlank(schemaVersions.get(schema));
if (scala)
out.println("value = %s(", out.ref("scala.Array"));
else if (kotlin)
out.println("value = [");
else
out.println("value = {");
out.println("\"https://www.jooq.org\",");
out.println("\"jOOQ version:%s\"%s", Constants.VERSION, (hasCatalogVersion || hasSchemaVersion ? "," : ""));
if (hasCatalogVersion)
out.println("\"catalog version:%s\"%s", escapeString(catalogVersions.get(catalog)), (hasSchemaVersion ? "," : ""));
if (hasSchemaVersion)
out.println("\"schema version:%s\"", escapeString(schemaVersions.get(schema)));
if (scala)
out.println("),");
else if (kotlin)
out.println("],");
else
out.println("},");
if (generateGeneratedAnnotationDate())
out.println("date = \"" + isoDate + "\",");
out.println("comments = \"This class is generated by jOOQ\"");
} else {
if (scala)
out.println("value = %s(", out.ref("scala.Array"));
else if (kotlin)
out.println("value = [");
else
out.println("value = {");
out.println("\"https://www.jooq.org\",");
out.println("\"jOOQ version:%s\"", Constants.VERSION);
if (scala)
out.println("),");
else if (kotlin)
out.println("],");
else
out.println("},");
out.println("comments = \"This class is generated by jOOQ\"");
}
out.println(")");
}
if (scala) {
} else if (kotlin)
out.println("@Suppress(\"UNCHECKED_CAST\")");
else
out.println("@%s({ \"all\", \"unchecked\", \"rawtypes\" })", out.ref("java.lang.SuppressWarnings"));
}
use of org.jooq.tools.reflect.ReflectException in project jOOQ by jOOQ.
the class MiniJAXB method append.
/**
* Appends a <code>second</code> JAXB annotated object to a
* <code>first</code> one using Maven's
* <code>combine.children="append"</code> semantics.
*
* @return The modified <code>first</code> argument.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> T append(T first, T second) {
if (first == null)
return second;
if (second == null)
return first;
Class<T> klass = (Class<T>) first.getClass();
if (klass != second.getClass())
throw new IllegalArgumentException("Can only append identical types");
else // [#8527] support enum types
if (klass.isEnum())
return first;
// We're assuming that XJC generated objects are all in the same package
Package pkg = klass.getPackage();
try {
T defaults = klass.getDeclaredConstructor().newInstance();
for (Method setter : klass.getMethods()) {
if (setter.getName().startsWith("set")) {
Method getter;
try {
getter = klass.getMethod("get" + setter.getName().substring(3));
} catch (NoSuchMethodException e) {
getter = klass.getMethod("is" + setter.getName().substring(3));
}
Class<?> childType = setter.getParameterTypes()[0];
Object firstChild = getter.invoke(first);
Object secondChild = getter.invoke(second);
Object defaultChild = getter.invoke(defaults);
if (Collection.class.isAssignableFrom(childType))
((List) firstChild).addAll((List) secondChild);
else if (secondChild != null && (firstChild == null || firstChild.equals(defaultChild)))
setter.invoke(first, secondChild);
else if (secondChild != null && pkg == childType.getPackage())
append(firstChild, secondChild);
else
// All other types cannot be merged
;
}
}
} catch (Exception e) {
throw new ReflectException(e);
}
return first;
}
use of org.jooq.tools.reflect.ReflectException in project jOOQ by jOOQ.
the class DefaultRecordMapper method init.
private final void init(E instance) {
Boolean debugVTFL = null;
Boolean debugVTCP = null;
Boolean debugMutable = null;
Boolean debugMutableConstructors = null;
Boolean debugCPSettings = null;
Boolean debugRC = null;
Boolean debugRCSettings = null;
Boolean debugKClass = null;
Boolean debugKSettings = null;
Boolean debugMatchDegreeFlat = null;
Boolean debugMatchDegreeNested = null;
// Arrays can be mapped easily
if (type.isArray()) {
delegate = new ArrayMapper(instance);
return;
}
if (Stream.class.isAssignableFrom(type)) {
delegate = r -> (E) Stream.of(((FieldsImpl<R>) rowType).mapper(configuration, Object[].class).map(r));
return;
}
// [#10071] [#11148] Primitive types are abstract! They're mapped by a ConverterProvider only later
if (Modifier.isAbstract(type.getModifiers()) && !type.isPrimitive()) {
delegate = new ProxyMapper();
return;
}
// [#2989] [#2836] Records are mapped
if (AbstractRecord.class.isAssignableFrom(type)) {
delegate = (RecordMapper<R, E>) new RecordToRecordMapper();
return;
}
// [#10071] Single-field Record1 types can be mapped if there is a ConverterProvider allowing for this mapping
if ((debugVTFL = fields.length == 1) && (debugVTCP = Tools.converter(configuration, instance, (Class) fields[0].getType(), type) != null)) {
delegate = new ValueTypeMapper();
return;
}
// [#1340] Allow for using non-public default constructors
try {
MutablePOJOMapper m = new MutablePOJOMapper(new ConstructorCall<>(accessible(type.getDeclaredConstructor())), instance);
// If the no-args constructor is the only one, take it none-theless
if ((debugMutable = m.isMutable()) || (debugMutableConstructors = type.getDeclaredConstructors().length <= 1)) {
delegate = m;
return;
}
} catch (NoSuchMethodException ignore) {
debugMutable = false;
}
// [#1336] If no default constructor is present, check if there is a
// "matching" constructor with the same number of fields as this record
Constructor<E>[] constructors = (Constructor<E>[]) type.getDeclaredConstructors();
// [#6868] Prefer public constructors
Arrays.sort(constructors, (c1, c2) -> (c2.getModifiers() & Modifier.PUBLIC) - (c1.getModifiers() & Modifier.PUBLIC));
// present use those rather than matching constructors by the number of arguments
if (debugCPSettings = !FALSE.equals(configuration.settings().isMapConstructorPropertiesParameterNames())) {
for (Constructor<E> constructor : constructors) {
ConstructorProperties properties = constructor.getAnnotation(ConstructorProperties.class);
if (properties != null) {
delegate = new ImmutablePOJOMapper(constructor, constructor.getParameterTypes(), Arrays.asList(properties.value()), true);
return;
}
}
}
// [#7324] Map immutable Kotlin classes by parameter names if kotlin-reflect is on the classpath
if ((debugKClass = Tools.isKotlinAvailable()) && (debugKSettings = !FALSE.equals(configuration.settings().isMapConstructorParameterNamesInKotlin()))) {
try {
Reflect jvmClassMappingKt = Tools.ktJvmClassMapping();
Reflect kClasses = Tools.ktKClasses();
Reflect kTypeParameter = Tools.ktKTypeParameter();
Object klass = jvmClassMappingKt.call("getKotlinClass", type).get();
Reflect primaryConstructor = kClasses.call("getPrimaryConstructor", klass);
// It is a Kotlin class
if (debugKClass = primaryConstructor.get() != null) {
List<?> parameters = primaryConstructor.call("getParameters").get();
Class<?> klassType = Tools.ktKClass().type();
Method getJavaClass = jvmClassMappingKt.type().getMethod("getJavaClass", klassType);
List<String> parameterNames = new ArrayList<>(parameters.size());
Class<?>[] parameterTypes = new Class[parameters.size()];
for (int i = 0; i < parameterTypes.length; i++) {
Reflect parameter = Reflect.on(parameters.get(i));
Object typeClassifier = parameter.call("getType").call("getClassifier").get();
String name = parameter.call("getName").get();
// [#8578] If the constructor parameter is a KTypeParameter, we need an additional step to
// extract the first upper bounds' classifier, which (hopefully) is a KClass
parameterTypes[i] = (Class<?>) getJavaClass.invoke(jvmClassMappingKt.get(), (kTypeParameter.type().isInstance(typeClassifier) ? Reflect.on(typeClassifier).call("getUpperBounds").call("get", 0).call("getClassifier").get() : typeClassifier));
// [#8004] Clean up kotlin field name for boolean types
String typeName = parameterTypes[i].getName();
if (name.startsWith("is") && (boolean.class.getName().equalsIgnoreCase(typeName) || Boolean.class.getName().equals(typeName)))
name = getPropertyName(name);
parameterNames.add(name);
}
Constructor<E> javaConstructor = (Constructor<E>) accessible(this.type.getDeclaredConstructor(parameterTypes));
delegate = new ImmutablePOJOMapper(javaConstructor, javaConstructor.getParameterTypes(), parameterNames, true);
return;
}
} catch (ReflectException | InvocationTargetException | IllegalAccessException | NoSuchMethodException ignore) {
}
}
boolean mapConstructorParameterNames = TRUE.equals(configuration.settings().isMapConstructorParameterNames());
// (for a flat POJO)
for (boolean supportsNesting : new boolean[] { true, false }) {
for (Constructor<E> constructor : constructors) {
Class<?>[] parameterTypes = constructor.getParameterTypes();
// Match the first constructor by parameter length
if (parameterTypes.length == (supportsNesting ? prefixes().size() : fields.length)) {
if (supportsNesting)
debugMatchDegreeNested = true;
else
debugMatchDegreeFlat = true;
// [#4627] use parameter names from byte code if available
if (mapConstructorParameterNames) {
Parameter[] parameters = constructor.getParameters();
if (parameters != null && parameters.length > 0)
delegate = new ImmutablePOJOMapper(constructor, parameterTypes, collectParameterNames(parameters), supportsNesting);
}
if (delegate == null)
delegate = new ImmutablePOJOMapper(constructor, parameterTypes, emptyList(), supportsNesting);
return;
}
}
if (supportsNesting)
debugMatchDegreeNested = false;
else
debugMatchDegreeFlat = false;
}
// use the first available constructor (thus the choice is undeterministic)
if (mapConstructorParameterNames) {
Constructor<E> constructor = constructors[0];
Parameter[] parameters = constructor.getParameters();
if (parameters != null && parameters.length > 0) {
delegate = new ImmutablePOJOMapper(constructor, constructor.getParameterTypes(), collectParameterNames(parameters), false);
return;
}
}
throw new MappingException(("" + "No DefaultRecordMapper strategy applies to type $type for row type $rowType. Attempted strategies include (in this order):\n" + "- Is type an array (false)?\n" + "- Is type a Stream (false)?\n" + "- Does row type have only 1 column ($debugVTFL) and did ConverterProvider provide a Converter for type ($debugVTCP)?\n" + "- Is type abstract (false)?\n" + "- Is type a org.jooq.Record (false)?\n" + "- Is type a mutable POJO (a POJO with setters or non-final members: $debugMutable) and has a no-args constructor ($debugMutableConstructors)?\n" + "- Does type have a @ConstructorProperties annotated constructor (false) and is Settings.mapConstructorPropertiesParameterNames enabled ($debugCPSettings)?\n" + "- Is type a java.lang.Record ($debugRC) and is Settings.mapRecordComponentParameterNames enabled ($debugRCSettings)?\n" + "- Is type a kotlin class ($debugKClass) and is Settings.mapConstructorParameterNamesInKotlin enabled ($debugKSettings)?\n" + "- Is there a constructor that matches row type's degrees with nested fields ($debugMatchDegreeNested) or flat fields ($debugMatchDegreeFlat)\n" + "- Is Settings.mapConstructorParameterNames enabled ($debugMatchNames)\n" + "").replace("$type", type.toString()).replace("$rowType", rowType.toString()).replace("$debugVTFL", debug(debugVTFL)).replace("$debugVTCP", debug(debugVTCP)).replace("$debugCPSettings", debug(debugCPSettings)).replace("$debugMutableConstructors", debug(debugMutableConstructors)).replace("$debugMutable", debug(debugMutable)).replace("$debugRCSettings", debug(debugRCSettings)).replace("$debugRC", debug(debugRC)).replace("$debugKClass", debug(debugKClass)).replace("$debugKSettings", debug(debugKSettings)).replace("$debugMatchDegreeNested", debug(debugMatchDegreeNested)).replace("$debugMatchDegreeFlat", debug(debugMatchDegreeFlat)).replace("$debugMatchNames", debug(mapConstructorParameterNames)));
}
Aggregations