2 * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.common;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import java.lang.reflect.Constructor;
13 import java.lang.reflect.Modifier;
14 import java.util.Arrays;
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
21 abstract class AbstractCanonicalValueImplementationValidator extends ClassValue<Boolean> {
22 private static final Logger LOG = LoggerFactory.getLogger(AbstractCanonicalValueImplementationValidator.class);
25 protected final Boolean computeValue(final @Nullable Class<?> type) {
26 // Every DerivedString representation class must:
27 checkArgument(CanonicalValue.class.isAssignableFrom(type), "%s is not a DerivedString", type);
29 // be non-final and public
30 final int modifiers = type.getModifiers();
31 checkArgument(Modifier.isPublic(modifiers), "%s must be public", type);
32 checkArgument(!Modifier.isFinal(modifiers), "%s must not be final", type);
34 // have at least one public or protected constructor (for subclasses)
35 checkArgument(Arrays.stream(type.getDeclaredConstructors()).mapToInt(Constructor::getModifiers)
36 .anyMatch(mod -> Modifier.isProtected(mod) || Modifier.isPublic(mod)),
37 "%s must declare at least one protected or public constructor", type);
40 // have a non-final non-abstract validator() method
43 validator = type.getMethod("validator").getModifiers();
44 } catch (NoSuchMethodException e) {
45 throw new IllegalArgumentException(type + " must have a non-abstract non-final validator() method",
48 checkArgument(!Modifier.isFinal(validator), "%s must not have final validator()", type);
50 // have final toCanonicalString(), support(), hashCode() and equals(Object), compare(T) methods
51 checkFinalMethod(type, "toCanonicalString");
52 checkFinalMethod(type, "support");
53 checkFinalMethod(type, "hashCode");
54 checkFinalMethod(type, "equals", Object.class);
55 } catch (SecurityException e) {
56 LOG.warn("Cannot completely validate {}", type, e);
63 abstract void checkCompareTo(Class<?> type);
65 static void checkFinalMethod(final Class<?> type, final String name) {
67 checkFinalMethod(type.getMethod(name).getModifiers(), type, name, "");
68 } catch (NoSuchMethodException e) {
69 throw new IllegalArgumentException(type + " must have a final " + name + "() method", e);
73 static void checkFinalMethod(final Class<?> type, final String name, final Class<?> arg) {
74 final String argName = arg.getSimpleName();
76 checkFinalMethod(type.getMethod(name, arg).getModifiers(), type, name, argName);
77 } catch (NoSuchMethodException e) {
78 throw new IllegalArgumentException(type + " must have a final " + name + "(" + argName + ") method", e);
82 private static void checkFinalMethod(final int modifiers, final Class<?> type, final String name,
84 checkArgument(Modifier.isFinal(modifiers), "%s must have a final %s(%s) method", type, name, args);