You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bval.apache.org by rm...@apache.org on 2013/08/26 15:59:20 UTC
svn commit: r1517540 [7/15] - in /bval/branches/bval-11/bval-jsr: ./ src/
src/main/ src/main/appended-resources/
src/main/appended-resources/META-INF/ src/main/java/ src/main/java/org/
src/main/java/org/apache/ src/main/java/org/apache/bval/ src/main/j...
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultConstraintValidatorFactory.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.cdi.BValExtension;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorFactory;
+import javax.validation.ValidationException;
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+
+/**
+ * Description: create constraint instances with the default / no-arg constructor <br/>
+ */
+public class DefaultConstraintValidatorFactory implements ConstraintValidatorFactory, Closeable {
+ private final Collection< BValExtension.Releasable<?>> releasables = new CopyOnWriteArrayList<BValExtension.Releasable<?>>();
+ private Boolean useCdi = null; // store it to avoid NoClassDefFoundError when cdi is not present (it is slow) + lazily (to wait cdi is started)
+
+ /**
+ * Instantiate a Constraint.
+ *
+ * @return Returns a new Constraint instance
+ * The ConstraintFactory is <b>not</b> responsible for calling Constraint#initialize
+ */
+ public <T extends ConstraintValidator<?, ?>> T getInstance(final Class<T> constraintClass) {
+ if (useCdi == null) {
+ synchronized (this) {
+ if (useCdi == null) {
+ try {
+ useCdi = BValExtension.getInstance() != null && BValExtension.getInstance().getBeanManager() != null;
+ } catch (final NoClassDefFoundError error) {
+ useCdi = false;
+ } catch (final Exception e) {
+ useCdi = false;
+ }
+ }
+ }
+ }
+
+ // 2011-03-27 jw: Do not use PrivilegedAction.
+ // Otherwise any user code would be executed with the privileges of this class.
+ try {
+ if (useCdi) {
+ try {
+ final BValExtension.Releasable<T> instance = BValExtension.inject(constraintClass);
+ releasables.add(instance);
+ return instance.getInstance();
+ } catch (final Exception e) {
+ return constraintClass.newInstance();
+ } catch (final NoClassDefFoundError error) {
+ return constraintClass.newInstance();
+ }
+ }
+ return constraintClass.newInstance();
+ } catch (final Exception ex) {
+ throw new ValidationException("Cannot instantiate : " + constraintClass, ex);
+ }
+ }
+
+ public void releaseInstance(final ConstraintValidator<?, ?> instance) {
+ // no-op
+ }
+
+ public void close() throws IOException {
+ for (final BValExtension.Releasable<?> releasable : releasables) {
+ // ensure to call this callback
+ releaseInstance(ConstraintValidator.class.cast(releasable.getInstance()));
+ releasable.release();
+ }
+ releasables.clear();
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultMessageInterpolator.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.el.MessageEvaluator;
+import org.apache.bval.util.reflection.Reflection;
+import org.apache.commons.lang3.ArrayUtils;
+
+import javax.validation.MessageInterpolator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Description: Resource bundle backed message interpolator.
+ * This message resolver resolve message descriptors
+ * into human-readable messages. It uses ResourceBundles to find the messages.
+ * This class is threadsafe.<br/>
+ */
+public class DefaultMessageInterpolator implements MessageInterpolator {
+ private static final Logger log = Logger.getLogger(DefaultMessageInterpolator.class.getName());
+ private static final boolean LOG_FINEST = log.isLoggable(Level.FINEST);
+ private static final String DEFAULT_VALIDATION_MESSAGES = "org.apache.bval.jsr.ValidationMessages";
+ private static final String USER_VALIDATION_MESSAGES = "ValidationMessages";
+
+ /** Regular expression used to do message interpolation. */
+ private static final Pattern messageParameterPattern = Pattern.compile("(\\{[\\w\\.]+\\})");
+
+ /** The default locale for the current user. */
+ private Locale defaultLocale;
+
+ /** User specified resource bundles hashed against their locale. */
+ private final Map<Locale, ResourceBundle> userBundlesMap =
+ new ConcurrentHashMap<Locale, ResourceBundle>();
+
+ /** Builtin resource bundles hashed against their locale. */
+ private final Map<Locale, ResourceBundle> defaultBundlesMap = new ConcurrentHashMap<Locale, ResourceBundle>();
+
+ private final MessageEvaluator evaluator;
+
+ /**
+ * Create a new DefaultMessageInterpolator instance.
+ */
+ public DefaultMessageInterpolator() {
+ this(null);
+ }
+
+ /**
+ * Create a new DefaultMessageInterpolator instance.
+ * @param resourceBundle
+ */
+ public DefaultMessageInterpolator(ResourceBundle resourceBundle) {
+ defaultLocale = Locale.getDefault();
+
+ // feed the cache with defaults at least
+ findDefaultResourceBundle(defaultLocale);
+ if (resourceBundle == null) {
+ findUserResourceBundle(defaultLocale);
+ } else {
+ userBundlesMap.put(defaultLocale, resourceBundle);
+ }
+
+ MessageEvaluator ev = null;
+ try {
+ ev = MessageEvaluator.class.cast(getClass().getClassLoader().loadClass("org.apache.bval.el.ELFacade").newInstance());
+ } catch (final Throwable e) { // can be exception or error
+ // no-op
+ }
+ evaluator = ev;
+ }
+
+ /** {@inheritDoc} */
+ public String interpolate(String message, Context context) {
+ // probably no need for caching, but it could be done by parameters since the map
+ // is immutable and uniquely built per Validation definition, the comparison has to be based on == and not equals though
+ return interpolate(message, context, defaultLocale);
+ }
+
+ /** {@inheritDoc} */
+ public String interpolate(String message, Context context, Locale locale) {
+ return interpolateMessage(message,
+ context.getConstraintDescriptor().getAttributes(), locale, context.getValidatedValue());
+ }
+
+ /**
+ * Runs the message interpolation according to algorithm specified in JSR 303.
+ * <br/>
+ * Note:
+ * <br/>
+ * Lookups in user bundles are recursive whereas lookups in default bundle are not!
+ *
+ * @param message the message to interpolate
+ * @param annotationParameters the parameters of the annotation for which to interpolate this message
+ * @param locale the <code>Locale</code> to use for the resource bundle.
+ * @return the interpolated message.
+ */
+ private String interpolateMessage(String message,
+ Map<String, Object> annotationParameters,
+ Locale locale, Object validatedValue) {
+ ResourceBundle userResourceBundle = findUserResourceBundle(locale);
+ ResourceBundle defaultResourceBundle = findDefaultResourceBundle(locale);
+
+ String userBundleResolvedMessage;
+ String resolvedMessage = message;
+ boolean evaluatedDefaultBundleOnce = false;
+ do {
+ // search the user bundle recursive (step1)
+ userBundleResolvedMessage =
+ replaceVariables(resolvedMessage, userResourceBundle, locale, true);
+
+ // exit condition - we have at least tried to validate against the default bundle and there were no
+ // further replacements
+ if (evaluatedDefaultBundleOnce &&
+ !hasReplacementTakenPlace(userBundleResolvedMessage, resolvedMessage)) {
+ break;
+ }
+
+ // search the default bundle non recursive (step2)
+ resolvedMessage = replaceVariables(userBundleResolvedMessage,
+ defaultResourceBundle, locale, false);
+
+ evaluatedDefaultBundleOnce = true;
+ } while (true);
+
+ // resolve annotation attributes (step 4)
+ resolvedMessage = replaceAnnotationAttributes(resolvedMessage, annotationParameters);
+
+ // EL handling
+ if (evaluator != null) {
+ resolvedMessage = evaluator.interpolate(resolvedMessage, annotationParameters, validatedValue);
+ }
+
+ // curly braces need to be scaped in the original msg, so unescape them now
+ resolvedMessage = resolvedMessage.replace( "\\{", "{" ).replace( "\\}", "}" ).replace( "\\\\", "\\" ).replace( "\\$", "$" );
+
+ return resolvedMessage;
+ }
+
+ private boolean hasReplacementTakenPlace(String origMessage, String newMessage) {
+ return !origMessage.equals(newMessage);
+ }
+
+ /**
+ * Search current thread classloader for the resource bundle. If not found, search validator (this) classloader.
+ *
+ * @param locale The locale of the bundle to load.
+ * @return the resource bundle or <code>null</code> if none is found.
+ */
+ private ResourceBundle getFileBasedResourceBundle(Locale locale) {
+ ResourceBundle rb = null;
+ final ClassLoader classLoader = Reflection.INSTANCE.getClassLoader(DefaultMessageInterpolator.class);
+ if (classLoader != null) {
+ rb = loadBundle(classLoader, locale,
+ USER_VALIDATION_MESSAGES + " not found by thread local classloader");
+ }
+
+ // 2011-03-27 jw: No privileged action required.
+ // A class can always access the classloader of itself and of subclasses.
+ if (rb == null) {
+ rb = loadBundle(getClass().getClassLoader(), locale, USER_VALIDATION_MESSAGES + " not found by validator classloader");
+ }
+ if (LOG_FINEST) {
+ if (rb != null) {
+ log.log(Level.FINEST, String.format("%s found", USER_VALIDATION_MESSAGES));
+ } else {
+ log.log(Level.FINEST, String.format("%s not found. Delegating to %s", USER_VALIDATION_MESSAGES, DEFAULT_VALIDATION_MESSAGES));
+ }
+ }
+ return rb;
+ }
+
+ private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale,
+ String message) {
+ ResourceBundle rb = null;
+ try {
+ rb = ResourceBundle.getBundle(USER_VALIDATION_MESSAGES, locale, classLoader);
+ } catch (final MissingResourceException e) {
+ log.fine(message);
+ }
+ return rb;
+ }
+
+ private String replaceVariables(String message, ResourceBundle bundle, Locale locale,
+ boolean recurse) {
+ final Matcher matcher = messageParameterPattern.matcher(message);
+ final StringBuffer sb = new StringBuffer(64);
+ String resolvedParameterValue;
+ while (matcher.find()) {
+ final String parameter = matcher.group(1);
+ resolvedParameterValue = resolveParameter(parameter, bundle, locale, recurse);
+
+ matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue));
+ }
+ matcher.appendTail(sb);
+ return sb.toString();
+ }
+
+ private String replaceAnnotationAttributes(final String message,
+ final Map<String, Object> annotationParameters) {
+ Matcher matcher = messageParameterPattern.matcher(message);
+ StringBuffer sb = new StringBuffer(64);
+ while (matcher.find()) {
+ String resolvedParameterValue;
+ String parameter = matcher.group(1);
+ Object variable = annotationParameters.get(removeCurlyBrace(parameter));
+ if (variable != null) {
+ if (variable.getClass().isArray()) {
+ resolvedParameterValue = ArrayUtils.toString(variable);
+ } else {
+ resolvedParameterValue = variable.toString();
+ }
+ } else {
+ resolvedParameterValue = parameter;
+ }
+ matcher.appendReplacement(sb, sanitizeForAppendReplacement(resolvedParameterValue));
+ }
+ matcher.appendTail(sb);
+ return sb.toString();
+ }
+
+ private String resolveParameter(String parameterName, ResourceBundle bundle,
+ Locale locale, boolean recurse) {
+ String parameterValue;
+ try {
+ if (bundle != null) {
+ parameterValue = bundle.getString(removeCurlyBrace(parameterName));
+ if (recurse) {
+ parameterValue = replaceVariables(parameterValue, bundle, locale, recurse);
+ }
+ } else {
+ parameterValue = parameterName;
+ }
+ } catch (final MissingResourceException e) {
+ // return parameter itself
+ parameterValue = parameterName;
+ }
+
+ return parameterValue;
+ }
+
+ private String removeCurlyBrace(String parameter) {
+ return parameter.substring(1, parameter.length() - 1);
+ }
+
+ private ResourceBundle findDefaultResourceBundle(Locale locale) {
+ ResourceBundle bundle = defaultBundlesMap.get(locale);
+ if (bundle == null)
+ {
+ bundle = ResourceBundle.getBundle(DEFAULT_VALIDATION_MESSAGES, locale);
+ defaultBundlesMap.put(locale, bundle);
+ }
+ return bundle;
+ }
+
+ private ResourceBundle findUserResourceBundle(Locale locale) {
+ ResourceBundle bundle = userBundlesMap.get(locale);
+ if (bundle == null)
+ {
+ bundle = getFileBasedResourceBundle(locale);
+ if (bundle != null) {
+ userBundlesMap.put(locale, bundle);
+ }
+ }
+ return bundle;
+ }
+
+ /**
+ * Set the default locale used by this {@link DefaultMessageInterpolator}.
+ * @param locale
+ */
+ public void setLocale(Locale locale) {
+ defaultLocale = locale;
+ }
+
+ /**
+ * Escapes the string to comply with
+ * {@link Matcher#appendReplacement(StringBuffer, String)} requirements.
+ *
+ * @param src
+ * The original string.
+ * @return The sanitized string.
+ */
+ private String sanitizeForAppendReplacement(String src) {
+ return src.replace("\\", "\\\\").replace("$", "\\$");
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/DefaultValidationProviderResolver.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.bval.jsr;
+
+
+import javax.validation.ValidationException;
+import javax.validation.ValidationProviderResolver;
+import javax.validation.spi.ValidationProvider;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+public class DefaultValidationProviderResolver implements ValidationProviderResolver {
+
+ //TODO - Spec recommends caching per classloader
+ private static final String SPI_CFG =
+ "META-INF/services/javax.validation.spi.ValidationProvider";
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<ValidationProvider<?>> getValidationProviders() {
+ List<ValidationProvider<?>> providers = new ArrayList<ValidationProvider<?>>();
+ try {
+ // get our classloader
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if (cl == null)
+ cl = DefaultValidationProviderResolver.class.getClassLoader();
+ // find all service provider cfgs
+ Enumeration<URL> cfgs = cl.getResources(SPI_CFG);
+ while (cfgs.hasMoreElements()) {
+ URL url = cfgs.nextElement();
+ BufferedReader br = null;
+ try {
+ br = new BufferedReader(new InputStreamReader(url.openStream()), 256);
+ String line = br.readLine();
+ // cfgs may contain multiple providers and/or comments
+ while (line != null) {
+ line = line.trim();
+ if (!line.startsWith("#")) {
+ try {
+ // try loading the specified class
+ final Class<?> provider = cl.loadClass(line);
+ // create an instance to return
+ final ValidationProvider<?> vp;
+ if (System.getSecurityManager() == null) {
+ try {
+ vp = (ValidationProvider<?>) provider.newInstance();
+ } catch (final Exception ex) {
+ throw new ValidationException("Cannot instantiate : " + provider, ex);
+ }
+ } else {
+ vp = AccessController.doPrivileged(new PrivilegedAction<ValidationProvider<?>>() {
+ public ValidationProvider<?> run() {
+ try {
+ return (ValidationProvider<?>) provider.newInstance();
+ } catch (final Exception ex) {
+ throw new ValidationException("Cannot instantiate : " + provider, ex);
+ }
+ }
+ });
+ }
+ providers.add(vp);
+
+ } catch (ClassNotFoundException e) {
+ throw new ValidationException("Failed to load provider " +
+ line + " configured in file " + url, e);
+ }
+ }
+ line = br.readLine();
+ }
+ br.close();
+ } catch (IOException e) {
+ throw new ValidationException("Error trying to read " + url, e);
+ } finally {
+ if (br != null)
+ br.close();
+ }
+ }
+ } catch (IOException e) {
+ throw new ValidationException("Error trying to read a " + SPI_CFG, e);
+ }
+ // caller must handle the case of no providers found
+ return providers;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ElementDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ElementDescriptorImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ElementDescriptorImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/ElementDescriptorImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.jsr.groups.Group;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.Validation;
+
+import javax.validation.ConstraintDeclarationException;
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+import javax.validation.metadata.GroupConversionDescriptor;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Description: MetaData class<br/>
+ */
+public abstract class ElementDescriptorImpl implements ElementDescriptor {
+ private final Set<GroupConversionDescriptor> groupConversions = new CopyOnWriteArraySet<GroupConversionDescriptor>();
+ private boolean cascaded;
+ private final Collection<Object> validated = new CopyOnWriteArraySet<Object>();
+
+ /**
+ * Get a set of {@link ConstraintDescriptor}s from the specified array of
+ * {@link Validation}s.
+ *
+ * @param validations
+ * @return {@link ConstraintDescriptor} set
+ */
+ protected static Set<ConstraintDescriptor<?>> getConstraintDescriptors(final Validation[] validations) {
+ final Set<ConstraintDescriptor<?>> result = new HashSet<ConstraintDescriptor<?>>(validations.length);
+ for (Validation validation : validations) {
+ if (validation instanceof ConstraintValidation<?>) {
+ result.add((ConstraintValidation<?>) validation);
+ }
+ }
+ return result;
+ }
+
+ /** the MetaBean of this element */
+ protected final MetaBean metaBean;
+
+ /** the raw type of this element */
+ protected final Class<?> elementClass;
+
+ private Set<ConstraintDescriptor<?>> constraintDescriptors;
+
+ private final Map<Group, Group> groupMapping = new HashMap<Group, Group>();
+
+ /**
+ * Create a new ElementDescriptorImpl instance.
+ *
+ * @param metaBean
+ * @param elementClass
+ * @param validations
+ */
+ protected ElementDescriptorImpl(MetaBean metaBean, Class<?> elementClass, Validation[] validations) {
+ this.metaBean = metaBean;
+ this.elementClass = elementClass;
+ setConstraintDescriptors(getConstraintDescriptors(validations));
+ }
+
+ /**
+ * Create a new ElementDescriptorImpl instance.
+ *
+ * @param elementClass
+ * @param validations
+ */
+ protected ElementDescriptorImpl(Class<?> elementClass, Validation[] validations) {
+ this(null, elementClass, validations);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return Statically defined returned type.
+ */
+ public Class<?> getElementClass() {
+ return elementClass;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public ElementDescriptor.ConstraintFinder findConstraints() {
+ return new ConstraintFinderImpl(metaBean, new HashSet((Set) constraintDescriptors));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
+ return constraintDescriptors.isEmpty() ? Collections.<ConstraintDescriptor<?>> emptySet() : Collections
+ .unmodifiableSet(constraintDescriptors);
+ }
+
+ /**
+ * Get the mutable {@link ConstraintDescriptor} {@link Set}.
+ *
+ * @return Set of {@link ConstraintDescriptor}
+ */
+ public Set<ConstraintDescriptor<?>> getMutableConstraintDescriptors() {
+ return constraintDescriptors;
+ }
+
+ /**
+ * {@inheritDoc} return true if at least one constraint declaration is
+ * present on the element.
+ */
+ public boolean hasConstraints() {
+ return !getConstraintDescriptors().isEmpty();
+ }
+
+ /**
+ * Set the constraintDescriptors for this element.
+ *
+ * @param constraintDescriptors
+ * to set
+ */
+ public void setConstraintDescriptors(Set<ConstraintDescriptor<?>> constraintDescriptors) {
+ this.constraintDescriptors = constraintDescriptors;
+ }
+
+ /**
+ * Get the model {@link MetaBean} used.
+ *
+ * @return MetaBean
+ */
+ public MetaBean getMetaBean() {
+ return metaBean;
+ }
+
+ public void addGroupMapping(final Group from, final Group to) {
+ groupMapping.put(from, to);
+ }
+
+ public Group mapGroup(final Group current) {
+ final Group mapping = groupMapping.get(current);
+ if (mapping != null) {
+ return mapping;
+ }
+ return current;
+ }
+
+ public Set<GroupConversionDescriptor> getGroupConversions() {
+ return groupConversions;
+ }
+
+ public void addGroupConversion(final GroupConversionDescriptor descriptor) {
+ groupConversions.add(descriptor);
+ final Group from = new Group(descriptor.getFrom());
+ if (mapGroup(from) != from) { // ref == is fine
+ throw new ConstraintDeclarationException("You can't map twice from the same group");
+ }
+ addGroupMapping(from, new Group(descriptor.getTo()));
+ }
+
+ public boolean isCascaded() {
+ return cascaded;
+ }
+
+ public void setCascaded(final boolean cascaded) {
+ this.cascaded = cascaded;
+ }
+
+ public boolean isValidated(final Object object) {
+ return validated.contains(object);
+ }
+
+ public void setValidated(final Object object) {
+ this.validated.add(object);
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GraphBeanIdentity.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+/**
+ * Class that stores the needed properties to avoid circular paths when
+ * validating an object graph.
+ * <p>
+ * These properties are:
+ * <ul>
+ * <li>The ref of the bean to which the validation would be applied.</li>
+ * <li>The current group being validated.</li>
+ * </ul>
+ *
+ * FIXME: Owner is currently not used in identity checking, and probably
+ * never will be. So it is likely to be deleted.
+ *
+ * @author Carlos Vara
+ */
+public class GraphBeanIdentity {
+
+ private final Object bean;
+ private final Class<?> group;
+ private final Class<?> owner;
+
+ /**
+ * Create a new GraphBeanIdentity instance.
+ * @param bean
+ * @param group
+ * @param owner
+ */
+ public GraphBeanIdentity(Object bean, Class<?> group, Class<?> owner) {
+ this.bean = bean;
+ this.group = group;
+ this.owner = owner;
+ }
+
+ /**
+ * Get the bean.
+ * @return Object
+ */
+ public Object getBean() {
+ return bean;
+ }
+
+ /**
+ * Get the group being validated.
+ * @return Class
+ */
+ public Class<?> getGroup() {
+ return group;
+ }
+
+ /**
+ * Get the owning class
+ * @return
+ */
+ public Class<?> getOwner() {
+ return owner;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (!(obj instanceof GraphBeanIdentity)) {
+ return false;
+ }
+
+ GraphBeanIdentity other = (GraphBeanIdentity) obj;
+
+ // Bean ref must be the same
+ if (this.bean != other.bean) {
+ return false;
+ }
+
+ // Group ref must be the same
+ if (this.group != other.group) {
+ return false;
+ }
+
+// // Owner ref must be the same
+// if (this.owner != other.owner) {
+// return false;
+// }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((this.bean == null) ? 0 : this.bean.hashCode());
+ result = prime * result
+ + ((this.group == null) ? 0 : this.group.hashCode());
+// result = prime * result
+// + ((this.owner == null) ? 0 : this.owner.hashCode());
+ return result;
+ }
+
+
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContext.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContext.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContext.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContext.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.bval.jsr;
+
+
+import org.apache.bval.jsr.groups.Group;
+import org.apache.bval.jsr.groups.Groups;
+import org.apache.bval.jsr.util.PathImpl;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.ValidationContext;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ElementKind;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.Path;
+import javax.validation.TraversableResolver;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Description: JSR-303 {@link ValidationContext} extension. <br/>
+ */
+public interface GroupValidationContext<T>
+ extends ValidationContext<ConstraintValidationListener<T>> {
+
+ /**
+ * Get the groups of this {@link GroupValidationContext}.
+ * @return the groups in their sequence for validation
+ */
+ Groups getGroups();
+
+ void setCurrentGroups(Groups groups);
+
+ /**
+ * Set the current {@link Group}.
+ * @param group to set
+ */
+ void setCurrentGroup(Group group);
+
+ /**
+ * Get the current {@link Group}.
+ * @return Group
+ */
+ Group getCurrentGroup();
+
+ /**
+ * Get the property path.
+ * @return {@link PathImpl}
+ */
+ PathImpl getPropertyPath();
+
+ /**
+ * Get the root {@link MetaBean}.
+ * @return {@link MetaBean}
+ */
+ MetaBean getRootMetaBean();
+
+ /**
+ * Set the {@link ConstraintValidation}.
+ * @param constraint to set
+ */
+ void setConstraintValidation(ConstraintValidation<?> constraint);
+
+ /**
+ * Get the {@link ConstraintValidation}.
+ * @return {@link ConstraintValidation}
+ */
+ ConstraintValidation<?> getConstraintValidation();
+
+ /**
+ * Get the value being validated.
+ * @return Object
+ */
+ Object getValidatedValue();
+
+ /**
+ * Set a fixed value for the context.
+ * @param value to set
+ */
+ void setFixedValue(Object value);
+
+ /**
+ * Get the message resolver.
+ * @return {@link MessageInterpolator}
+ */
+ MessageInterpolator getMessageResolver();
+
+ /**
+ * Get the {@link TraversableResolver}.
+ * @return {@link TraversableResolver}
+ */
+ TraversableResolver getTraversableResolver();
+
+ /**
+ * Accumulate a validated constraint.
+ * @param constraint
+ * @return true when the constraint for the object in this path was not
+ * already validated in this context
+ */
+ boolean collectValidated(ConstraintValidator<?, ?> constraint);
+
+ /**
+ * Get the current owning class.
+ * @return Class
+ */
+ Class<?> getCurrentOwner();
+
+ /**
+ * Set the current owning class.
+ * @param currentOwner to set
+ */
+ void setCurrentOwner(Class<?> currentOwner);
+
+ void setKind(ElementKind type);
+
+ ElementKind getElementKind();
+
+ Object getReturnValue();
+
+ Object[] getParameters();
+
+ void setParameters(Object[] parameters);
+
+ void setReturnValue(Object returnValue);
+
+ ParameterNameProvider getParameterNameProvider();
+
+ void setMethod(Method method);
+
+ Method getMethod();
+
+ void setConstructor(Constructor<?> method);
+
+ Constructor<?> getConstructor();
+
+ void moveDown(Path.Node node);
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContextImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContextImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContextImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/GroupValidationContextImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.BeanValidationContext;
+import org.apache.bval.jsr.groups.Group;
+import org.apache.bval.jsr.groups.Groups;
+import org.apache.bval.jsr.resolver.CachingTraversableResolver;
+import org.apache.bval.jsr.util.NodeImpl;
+import org.apache.bval.jsr.util.PathImpl;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaProperty;
+import org.apache.bval.util.AccessStrategy;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ElementKind;
+import javax.validation.MessageInterpolator;
+import javax.validation.ParameterNameProvider;
+import javax.validation.Path;
+import javax.validation.TraversableResolver;
+import javax.validation.ValidationException;
+import javax.validation.metadata.ConstraintDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Description: instance per validation process, not thread-safe<br/>
+ */
+final class GroupValidationContextImpl<T> extends BeanValidationContext<ConstraintValidationListener<T>> implements
+ GroupValidationContext<T>, MessageInterpolator.Context {
+
+ private final MessageInterpolator messageResolver;
+ private final PathImpl path;
+ private final MetaBean rootMetaBean;
+ private final ParameterNameProvider parameterNameProvider;
+
+ /**
+ * the groups in the sequence of validation to take place
+ */
+ private Groups groups;
+ /**
+ * the current group during the validation process
+ */
+ private Group currentGroup;
+
+ private Class<?> currentOwner;
+
+ /**
+ * contains the validation constraints that have already been processed
+ * during this validation routine (as part of a previous group match)
+ */
+ private HashSet<ConstraintValidatorIdentity> validatedConstraints = new HashSet<ConstraintValidatorIdentity>();
+
+ private ConstraintValidation<?> constraintValidation;
+ private final TraversableResolver traversableResolver;
+
+ private Object[] parameters;
+ private Object returnValue;
+ private Method method;
+ private Constructor<?> constructor;
+
+ /**
+ * Create a new GroupValidationContextImpl instance.
+ *
+ * @param listener
+ * @param aMessageResolver
+ * @param traversableResolver
+ * @param parameterNameProvider
+ * @param rootMetaBean
+ */
+ public GroupValidationContextImpl(ConstraintValidationListener<T> listener, MessageInterpolator aMessageResolver,
+ TraversableResolver traversableResolver, ParameterNameProvider parameterNameProvider, MetaBean rootMetaBean) {
+ // inherited variable 'validatedObjects' is of type:
+ // HashMap<GraphBeanIdentity, Set<PathImpl>> in this class
+ super(listener, new HashMap<GraphBeanIdentity, Set<PathImpl>>());
+ this.messageResolver = aMessageResolver;
+ this.traversableResolver = CachingTraversableResolver.cacheFor(traversableResolver);
+ this.parameterNameProvider = parameterNameProvider;
+ this.rootMetaBean = rootMetaBean;
+ this.path = PathImpl.create();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCurrentIndex(Integer index) {
+ NodeImpl leaf = path.getLeafNode();
+ if (leaf.getName() == null) {
+ leaf.setIndex(index);
+ } else {
+ path.addNode(NodeImpl.atIndex(index));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setCurrentKey(Object key) {
+ NodeImpl leaf = path.getLeafNode();
+ if (leaf.getName() == null) {
+ leaf.setKey(key);
+ } else {
+ path.addNode(NodeImpl.atKey(key));
+ }
+ }
+
+ public void setKind(final ElementKind type) {
+ path.getLeafNode().setKind(type);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void moveDown(MetaProperty prop, AccessStrategy access) {
+ moveDown(prop.getName());
+ super.moveDown(prop, access);
+ }
+
+ @Override
+ public void moveDown(final String prop) {
+ path.addProperty(prop);
+ }
+
+ public void moveDown(final Path.Node node) {
+ path.addNode(node);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void moveUp(Object bean, MetaBean metaBean) {
+ NodeImpl leaf = path.getLeafNode();
+ if (leaf.isInIterable() && leaf.getName() != null) {
+ leaf.setName(null);
+ } else {
+ path.removeLeafNode();
+ }
+ super.moveUp(bean, metaBean); // call super!
+ }
+
+ /**
+ * {@inheritDoc} Here, state equates to bean identity + group.
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean collectValidated() {
+
+ // Combination of bean+group+owner (owner is currently ignored)
+ GraphBeanIdentity gbi = new GraphBeanIdentity(getBean(), getCurrentGroup().getGroup(), getCurrentOwner());
+
+ Set<PathImpl> validatedPathsForGBI = (Set<PathImpl>) validatedObjects.get(gbi);
+ if (validatedPathsForGBI == null) {
+ validatedPathsForGBI = new HashSet<PathImpl>();
+ validatedObjects.put(gbi, validatedPathsForGBI);
+ }
+
+ // If any of the paths is a subpath of the current path, there is a
+ // circular dependency, so return false
+ for (PathImpl validatedPath : validatedPathsForGBI) {
+ if (path.isSubPathOf(validatedPath)) {
+ return false;
+ }
+ }
+
+ // Else, add the currentPath to the set of validatedPaths
+ validatedPathsForGBI.add(PathImpl.copy(path));
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean collectValidated(ConstraintValidator<?, ?> constraint) {
+ ConstraintValidatorIdentity cvi = new ConstraintValidatorIdentity(getBean(), getPropertyPath(), constraint);
+ return this.validatedConstraints.add(cvi);
+ }
+
+ /**
+ * Reset the validated constraints.
+ */
+ public void resetValidatedConstraints() {
+ validatedConstraints.clear();
+ }
+
+ /**
+ * {@inheritDoc} If an associated object is validated, add the association
+ * field or JavaBeans property name and a dot ('.') as a prefix to the
+ * previous rules. uses prop[index] in property path for elements in
+ * to-many-relationships.
+ *
+ * @return the path in dot notation
+ */
+ public PathImpl getPropertyPath() {
+ PathImpl currentPath = PathImpl.copy(path);
+ if (getMetaProperty() != null) {
+ currentPath.addProperty(getMetaProperty().getName());
+ }
+ return currentPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MetaBean getRootMetaBean() {
+ return rootMetaBean;
+ }
+
+ /**
+ * Set the Groups.
+ *
+ * @param groups
+ */
+ public void setGroups(Groups groups) {
+ this.groups = groups;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Groups getGroups() {
+ return groups;
+ }
+
+ public void setCurrentGroups(final Groups g) {
+ groups = g;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Group getCurrentGroup() {
+ return currentGroup;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCurrentGroup(Group currentGroup) {
+ this.currentGroup = currentGroup;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setConstraintValidation(ConstraintValidation<?> constraint) {
+ constraintValidation = constraint;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintValidation<?> getConstraintValidation() {
+ return constraintValidation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConstraintDescriptor<?> getConstraintDescriptor() {
+ return constraintValidation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getValidatedValue() {
+ if (getMetaProperty() != null) {
+ return getPropertyValue(constraintValidation.getAccess());
+ } else {
+ return getBean();
+ }
+ }
+
+ public <T> T unwrap(Class<T> type) {
+ if (type.isInstance(this)) {
+ return type.cast(this);
+ }
+ throw new ValidationException("Type " + type + " not supported");
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public MessageInterpolator getMessageResolver() {
+ return messageResolver;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public TraversableResolver getTraversableResolver() {
+ return traversableResolver;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Class<?> getCurrentOwner() {
+ return this.currentOwner;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setCurrentOwner(Class<?> currentOwner) {
+ this.currentOwner = currentOwner;
+ }
+
+ public ElementKind getElementKind() {
+ return path.getLeafNode().getKind();
+ }
+
+ public Object getReturnValue() {
+ return returnValue;
+ }
+
+ public Object[] getParameters() {
+ return parameters;
+ }
+
+ public void setParameters(final Object[] parameters) {
+ this.parameters = parameters;
+ }
+
+ public void setReturnValue(final Object returnValue) {
+ this.returnValue = returnValue;
+ }
+
+ public ParameterNameProvider getParameterNameProvider() {
+ return parameterNameProvider;
+ }
+
+ public void setMethod(final Method method) {
+ this.method = method;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public Constructor<?> getConstructor() {
+ return constructor;
+ }
+
+ public void setConstructor(final Constructor<?> constructor) {
+ this.constructor = constructor;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/IncompatiblePropertyValueException.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/IncompatiblePropertyValueException.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/IncompatiblePropertyValueException.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/IncompatiblePropertyValueException.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import javax.validation.ValidationException;
+
+/**
+ * Internal exception thrown when trying to validate a value for a property for which it is not assignment-compatible.
+ *
+ * @version $Rev: 1031833 $ $Date: 2010-11-05 16:53:03 -0500 (Fri, 05 Nov 2010) $
+ *
+ * @author Matt Benson
+ */
+public class IncompatiblePropertyValueException extends ValidationException {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Create a new {@link IncompatiblePropertyValueException} instance.
+ *
+ * @param message
+ */
+ public IncompatiblePropertyValueException(String message) {
+ super(message);
+ }
+
+ /**
+ * Create a new IncompatiblePropertyValueException instance.
+ */
+ public IncompatiblePropertyValueException() {
+ super();
+ }
+
+ /**
+ * Create a new IncompatiblePropertyValueException instance.
+ *
+ * @param message
+ * @param cause
+ */
+ public IncompatiblePropertyValueException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Create a new IncompatiblePropertyValueException instance.
+ *
+ * @param cause
+ */
+ public IncompatiblePropertyValueException(Throwable cause) {
+ super(cause);
+ }
+
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/InvocableElementDescriptor.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/InvocableElementDescriptor.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/InvocableElementDescriptor.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/InvocableElementDescriptor.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.Validation;
+
+import javax.validation.metadata.ConstraintDescriptor;
+import javax.validation.metadata.CrossParameterDescriptor;
+import javax.validation.metadata.ElementDescriptor;
+import javax.validation.metadata.ParameterDescriptor;
+import javax.validation.metadata.ReturnValueDescriptor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+public class InvocableElementDescriptor extends ElementDescriptorImpl implements ProcedureDescriptor {
+ private static final CopyOnWriteArraySet<ConstraintValidation<?>> NO_CONSTRAINTS = new CopyOnWriteArraySet<ConstraintValidation<?>>();
+
+ private ReturnValueDescriptor returnValueDescriptor;
+ private CrossParameterDescriptor crossParameterDescriptor;
+ private final List<ParameterDescriptor> parameterDescriptors = new ArrayList<ParameterDescriptor>();
+
+ protected InvocableElementDescriptor(final MetaBean metaBean, final Class<?> elementClass, final Validation[] validations) {
+ super(metaBean, elementClass, validations);
+ }
+
+ protected InvocableElementDescriptor(final Class<?> elementClass, final Validation[] validations) {
+ super(elementClass, validations);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<ParameterDescriptor> getParameterDescriptors() {
+ // index aligned
+ return parameterDescriptors;
+ }
+
+ public void setReturnValueDescriptor(final ReturnValueDescriptor returnValueDescriptor) {
+ this.returnValueDescriptor = returnValueDescriptor;
+ }
+
+ public CrossParameterDescriptor getCrossParameterDescriptor() {
+ return crossParameterDescriptor;
+ }
+
+ public void setCrossParameterDescriptor(final CrossParameterDescriptor crossParameterDescriptor) {
+ this.crossParameterDescriptor = crossParameterDescriptor;
+ }
+
+ /**
+ * Add the specified validations to this {@link org.apache.bval.jsr.MethodDescriptorImpl}.
+ * @param validations
+ */
+ void addValidations(Collection<ConstraintValidation<?>> validations) {
+ getMutableConstraintDescriptors().addAll(validations);
+ }
+
+ protected boolean hasConstrainedParameters() {
+ for (final ParameterDescriptor pd : getParameterDescriptors()) {
+ if (pd.isCascaded() || !pd.getConstraintDescriptors().isEmpty()) {
+ return true;
+ }
+ }
+ return getCrossParameterDescriptor().hasConstraints();
+ }
+
+ public ReturnValueDescriptor getReturnValueDescriptor() {
+ return returnValueDescriptor;
+ }
+
+ protected boolean hasConstrainedReturnValue() {
+ return getReturnValueDescriptor().isCascaded() || !getReturnValueDescriptor().getConstraintDescriptors().isEmpty();
+ }
+
+ @Override
+ public ElementDescriptor.ConstraintFinder findConstraints() {
+ return new ConstraintFinderImpl(metaBean, NO_CONSTRAINTS);
+ }
+
+ @Override
+ public Set<ConstraintDescriptor<?>> getConstraintDescriptors() {
+ return Set.class.cast(NO_CONSTRAINTS);
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrFeatures.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrFeatures.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrFeatures.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrFeatures.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.model.Features;
+
+/**
+ * Description: Contains MetaBean feature keys of additional features used in the implementation
+ * of JSR303<br/>
+ *
+ * @see org.apache.bval.model.FeaturesCapable
+ * @see org.apache.bval.model.Features
+ */
+public interface JsrFeatures {
+ interface Method extends Features.Property {
+ String MethodDescriptor = "MethodDescriptor";
+ }
+
+ interface Constructor extends Features.Property {
+ String ConstructorDescriptor = "ConstructorDescriptor";
+ }
+
+ /**
+ * JSR303 Property features
+ */
+ interface Property extends Features.Property {
+ /** INFO: cached PropertyDescriptorImpl of the property */
+ String PropertyDescriptor = "PropertyDescriptor";
+ /**
+ * INFO: Class[] with the groups to validate a REF_CASCADE
+ */
+ String REF_GROUPS = "refGroups";
+
+ // Collection<Annotation>
+ String ANNOTATIONS_TO_PROCESS = "annotationToProcess";
+ }
+
+ /**
+ * JSR303 bean features
+ */
+ interface Bean extends Features.Bean {
+ /**
+ * INFO: List of Group(Class) for {@link javax.validation.GroupSequence#value()}
+ * (redefined default group)
+ **/
+ String GROUP_SEQUENCE = "GroupSequence";
+
+// INFO: cached sorted Array with ValidationEntries
+// String VALIDATION_SEQUENCE = "ValidationSequence";
+
+ /**
+ * INFO: cached BeanDescriptorImpl of the bean
+ */
+ String BEAN_DESCRIPTOR = "BeanDescriptor";
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrMetaBeanFactory.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrMetaBeanFactory.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrMetaBeanFactory.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/JsrMetaBeanFactory.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,331 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.MetaBeanFactory;
+import org.apache.bval.jsr.groups.Group;
+import org.apache.bval.jsr.util.ClassHelper;
+import org.apache.bval.jsr.xml.MetaConstraint;
+import org.apache.bval.model.Meta;
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaConstructor;
+import org.apache.bval.model.MetaMethod;
+import org.apache.bval.model.MetaParameter;
+import org.apache.bval.model.MetaProperty;
+import org.apache.bval.util.AccessStrategy;
+import org.apache.bval.util.FieldAccess;
+import org.apache.bval.util.MethodAccess;
+import org.apache.bval.util.reflection.Reflection;
+
+import javax.validation.ConstraintDeclarationException;
+import javax.validation.GroupDefinitionException;
+import javax.validation.GroupSequence;
+import javax.validation.groups.ConvertGroup;
+import javax.validation.groups.Default;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Description: process the class annotations for JSR303 constraint validations to build the MetaBean with information
+ * from annotations and JSR303 constraint mappings (defined in xml)<br/>
+ */
+public class JsrMetaBeanFactory implements MetaBeanFactory {
+ /** Shared log instance */
+ // of dubious utility as it's static :/
+ protected static final Logger log = Logger.getLogger(JsrMetaBeanFactory.class.getName());
+
+ /** {@link ApacheFactoryContext} used */
+ protected final ApacheFactoryContext factoryContext;
+
+ /**
+ * {@link AnnotationProcessor} used.
+ */
+ protected AnnotationProcessor annotationProcessor;
+
+ /**
+ * Create a new Jsr303MetaBeanFactory instance.
+ *
+ * @param factoryContext
+ */
+ public JsrMetaBeanFactory(ApacheFactoryContext factoryContext) {
+ this.factoryContext = factoryContext;
+ this.annotationProcessor = new AnnotationProcessor(factoryContext);
+ }
+
+ /**
+ * {@inheritDoc} Add the validation features to the metabean that come from JSR303 annotations in the beanClass.
+ */
+ public void buildMetaBean(MetaBean metabean) {
+ try {
+ final Class<?> beanClass = metabean.getBeanClass();
+ processGroupSequence(beanClass, metabean);
+
+ // process class, superclasses and interfaces
+ List<Class<?>> classSequence = new ArrayList<Class<?>>();
+ ClassHelper.fillFullClassHierarchyAsList(classSequence, beanClass);
+
+ // start with superclasses and go down the hierarchy so that
+ // the child classes are processed last to have the chance to
+ // overwrite some declarations
+ // of their superclasses and that they see what they inherit at the
+ // time of processing
+ for (int i = classSequence.size() - 1; i >= 0; i--) {
+ Class<?> eachClass = classSequence.get(i);
+ if (eachClass == Serializable.class || eachClass == Cloneable.class) {
+ continue;
+ }
+
+ processClass(eachClass, metabean);
+ processGroupSequence(eachClass, metabean, "{GroupSequence:" + eachClass.getCanonicalName() + "}");
+ }
+
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalArgumentException(e.getTargetException());
+ }
+ }
+
+ /**
+ * Process class annotations, field and method annotations.
+ *
+ * @param beanClass
+ * @param metabean
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ private void processClass(Class<?> beanClass, MetaBean metabean) throws IllegalAccessException,
+ InvocationTargetException {
+
+ // if NOT ignore class level annotations
+ if (!factoryContext.getFactory().getAnnotationIgnores().isIgnoreAnnotations(beanClass)) {
+ annotationProcessor.processAnnotations(null, beanClass, beanClass, null, new AppendValidationToMeta(metabean));
+ }
+
+ final Collection<String> missingValid = new ArrayList<String>();
+
+ final Field[] fields = Reflection.INSTANCE.getDeclaredFields(beanClass);
+ for (final Field field : fields) {
+ MetaProperty metaProperty = metabean.getProperty(field.getName());
+ // create a property for those fields for which there is not yet a
+ // MetaProperty
+ if (!factoryContext.getFactory().getAnnotationIgnores().isIgnoreAnnotations(field)) {
+ AccessStrategy access = new FieldAccess(field);
+ boolean create = metaProperty == null;
+ if (create) {
+ metaProperty = addMetaProperty(metabean, access);
+ }
+ if (!annotationProcessor.processAnnotations(metaProperty, beanClass, field, access,
+ new AppendValidationToMeta(metaProperty)) && create) {
+ metabean.putProperty(metaProperty.getName(), null);
+ }
+
+ if (field.getAnnotation(ConvertGroup.class) != null) {
+ missingValid.add(field.getName());
+ }
+ }
+ }
+ final Method[] methods = Reflection.INSTANCE.getDeclaredMethods(beanClass);
+ for (final Method method : methods) {
+ String propName = null;
+ if (method.getParameterTypes().length == 0) {
+ propName = MethodAccess.getPropertyName(method);
+ }
+ if (propName != null) {
+ if (!factoryContext.getFactory().getAnnotationIgnores().isIgnoreAnnotations(method)) {
+ AccessStrategy access = new MethodAccess(propName, method);
+ MetaProperty metaProperty = metabean.getProperty(propName);
+ boolean create = metaProperty == null;
+ // create a property for those methods for which there is
+ // not yet a MetaProperty
+ if (create) {
+ metaProperty = addMetaProperty(metabean, access);
+ }
+ if (!annotationProcessor.processAnnotations(metaProperty, beanClass, method, access,
+ new AppendValidationToMeta(metaProperty)) && create) {
+ metabean.putProperty(propName, null);
+ }
+ }
+ }
+ }
+
+ addXmlConstraints(beanClass, metabean);
+
+ for (final String name : missingValid) {
+ final MetaProperty metaProperty = metabean.getProperty(name);
+ if (metaProperty != null && metaProperty.getFeature(JsrFeatures.Property.REF_CASCADE) == null) {
+ throw new ConstraintDeclarationException("@ConvertGroup needs @Valid");
+ }
+ }
+ missingValid.clear();
+ }
+
+ /**
+ * Add cascade validation and constraints from xml mappings
+ *
+ * @param beanClass
+ * @param metabean
+ * @throws IllegalAccessException
+ * @throws InvocationTargetException
+ */
+ private void addXmlConstraints(Class<?> beanClass, MetaBean metabean) throws IllegalAccessException,
+ InvocationTargetException {
+ for (final MetaConstraint<?, ? extends Annotation> metaConstraint : factoryContext.getFactory().getMetaConstraints(beanClass)) {
+ Meta meta;
+ AccessStrategy access = metaConstraint.getAccessStrategy();
+ boolean create = false;
+ if (access == null) { // class level
+ meta = null;
+ } else if (access.getElementType() == ElementType.METHOD && !metaConstraint.getMember().getName().startsWith("get")) { // TODO: better getter test
+ final Method method = Method.class.cast(metaConstraint.getMember());
+ meta = metabean.getMethod(method);
+ final MetaMethod metaMethod;
+ if (meta == null) {
+ meta = new MetaMethod(metabean, method);
+ metaMethod = MetaMethod.class.cast(meta);
+ metabean.addMethod(method, metaMethod);
+ } else {
+ metaMethod = MetaMethod.class.cast(meta);
+ }
+ final Integer index = metaConstraint.getIndex();
+ if (index != null && index >= 0) {
+ MetaParameter param = metaMethod.getParameter(index);
+ if (param == null) {
+ param = new MetaParameter(metaMethod, index);
+ metaMethod.addParameter(index, param);
+ }
+ param.addAnnotation(metaConstraint.getAnnotation());
+ } else {
+ metaMethod.addAnnotation(metaConstraint.getAnnotation());
+ }
+ continue;
+ } else if (access.getElementType() == ElementType.CONSTRUCTOR){
+ final Constructor<?> constructor = Constructor.class.cast(metaConstraint.getMember());
+ meta = metabean.getConstructor(constructor);
+ final MetaConstructor metaConstructor;
+ if (meta == null) {
+ meta = new MetaConstructor(metabean, constructor);
+ metaConstructor = MetaConstructor.class.cast(meta);
+ metabean.addConstructor(constructor, metaConstructor);
+ } else {
+ metaConstructor = MetaConstructor.class.cast(meta);
+ }
+ final Integer index = metaConstraint.getIndex();
+ if (index != null && index >= 0) {
+ MetaParameter param = metaConstructor.getParameter(index);
+ if (param == null) {
+ param = new MetaParameter(metaConstructor, index);
+ metaConstructor.addParameter(index, param);
+ }
+ param.addAnnotation(metaConstraint.getAnnotation());
+ } else {
+ metaConstructor.addAnnotation(metaConstraint.getAnnotation());
+ }
+ continue;
+ } else { // property level
+ meta = metabean.getProperty(access.getPropertyName());
+ create = meta == null;
+ if (create) {
+ meta = addMetaProperty(metabean, access);
+ }
+ }
+ if (!annotationProcessor.processAnnotation(metaConstraint.getAnnotation(), meta, beanClass,
+ metaConstraint.getAccessStrategy(), new AppendValidationToMeta(meta == null ? metabean : meta), false)
+ && create) {
+ metabean.putProperty(access.getPropertyName(), null);
+ }
+ }
+ for (final AccessStrategy access : factoryContext.getFactory().getValidAccesses(beanClass)) {
+ if (access.getElementType() == ElementType.PARAMETER) {
+ continue;
+ }
+
+ MetaProperty metaProperty = metabean.getProperty(access.getPropertyName());
+ boolean create = metaProperty == null;
+ if (create) {
+ metaProperty = addMetaProperty(metabean, access);
+ }
+ if (!annotationProcessor.addAccessStrategy(metaProperty, access) && create) {
+ metabean.putProperty(access.getPropertyName(), null);
+ }
+ }
+ }
+
+ private void processGroupSequence(Class<?> beanClass, MetaBean metabean) {
+ processGroupSequence(beanClass, metabean, JsrFeatures.Bean.GROUP_SEQUENCE);
+ }
+
+ private void processGroupSequence(Class<?> beanClass, MetaBean metabean, String key) {
+ GroupSequence annotation = beanClass.getAnnotation(GroupSequence.class);
+ List<Group> groupSeq = metabean.getFeature(key);
+ if (groupSeq == null) {
+ groupSeq = metabean.initFeature(key, new ArrayList<Group>(annotation == null ? 1 : annotation.value().length));
+ }
+ Class<?>[] groupClasses = factoryContext.getFactory().getDefaultSequence(beanClass);
+ if (groupClasses == null || groupClasses.length == 0) {
+ if (annotation == null) {
+ groupSeq.add(Group.DEFAULT);
+ return;
+ } else {
+ groupClasses = annotation.value();
+ }
+ }
+ boolean containsDefault = false;
+ for (final Class<?> groupClass : groupClasses) {
+ if (groupClass.getName().equals(beanClass.getName())) {
+ groupSeq.add(Group.DEFAULT);
+ containsDefault = true;
+ } else if (groupClass.getName().equals(Default.class.getName())) {
+ throw new GroupDefinitionException("'Default.class' must not appear in @GroupSequence! Use '"
+ + beanClass.getSimpleName() + ".class' instead.");
+ } else {
+ groupSeq.add(new Group(groupClass));
+ }
+ }
+ if (!containsDefault) {
+ throw new GroupDefinitionException("Redefined default group sequence must contain " + beanClass.getName());
+ }
+ log.log(Level.FINEST, String.format("Default group sequence for bean %s is: %s", beanClass.getName(), groupSeq));
+ }
+
+ /**
+ * Add a {@link MetaProperty} to a {@link MetaBean}.
+ * @param parentMetaBean
+ * @param access
+ * @return the created {@link MetaProperty}
+ */
+ public static MetaProperty addMetaProperty(MetaBean parentMetaBean, AccessStrategy access) {
+ final MetaProperty result = new MetaProperty();
+ final String name = access.getPropertyName();
+ result.setName(name);
+ result.setType(access.getJavaType());
+ parentMetaBean.putProperty(name, result);
+ return result;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptor.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptor.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptor.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptor.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.jsr;
+
+import javax.validation.metadata.ElementDescriptor;
+import javax.validation.metadata.ParameterDescriptor;
+import java.util.List;
+
+/**
+ * Description: This class will disappear when such
+ * functionality is part of the JSR303 specification.<br/>
+ */
+public interface MethodDescriptor extends ElementDescriptor {
+ /**
+ * Get the {@link javax.validation.metadata.ParameterDescriptor}s for this {@link org.apache.bval.jsr.MethodDescriptor}.
+ * @return {@link java.util.List} of {@link javax.validation.metadata.ParameterDescriptor}
+ */
+ List<ParameterDescriptor> getParameterDescriptors(); //index aligned
+
+ /**
+ * Learn whether the referenced method should be validated.
+ * @return boolean
+ */
+ boolean isCascaded();
+
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptorImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptorImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptorImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/MethodDescriptorImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.model.MetaBean;
+import org.apache.bval.model.MetaMethod;
+import org.apache.bval.model.Validation;
+
+import java.lang.reflect.Method;
+
+/**
+ * Description: {@link MethodDescriptor} implementation.<br/>
+ */
+public class MethodDescriptorImpl extends InvocableElementDescriptor implements javax.validation.metadata.MethodDescriptor, ProcedureDescriptor {
+ private static final Validation[] EMPTY_VALIDATION = new Validation[0];
+
+ private final String name;
+
+ protected MethodDescriptorImpl(final MetaBean metaBean, final Validation[] validations, final Method method) {
+ super(metaBean, method.getReturnType(), validations);
+ name = method.getName();
+ }
+
+ public MethodDescriptorImpl(final MetaBean bean, final MetaMethod metaMethod) {
+ super(bean, metaMethod.getMethod().getReturnType(), EMPTY_VALIDATION);
+ setCascaded(false);
+ this.name = metaMethod.getMethod().getName();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean hasConstrainedParameters() {
+ return super.hasConstrainedParameters();
+ }
+
+ public boolean hasConstrainedReturnValue() {
+ return super.hasConstrainedReturnValue();
+ }
+
+ @Override
+ public boolean hasConstraints() {
+ return false;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeBuilderCustomizableContextImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.jsr.util.LeafNodeBuilderCustomizableContextImpl;
+import org.apache.bval.jsr.util.NodeImpl;
+import org.apache.bval.jsr.util.PathImpl;
+
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ElementKind;
+
+public class NodeBuilderCustomizableContextImpl implements ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext {
+ private final PathImpl path;
+ private final ConstraintValidatorContextImpl context;
+ private final String template;
+
+ public NodeBuilderCustomizableContextImpl(final ConstraintValidatorContextImpl parent, final String messageTemplate, final PathImpl propertyPath) {
+ context = parent;
+ template = messageTemplate;
+ path = propertyPath;
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeContextBuilder inIterable() {
+ path.getLeafNode().setInIterable(true);
+ return new NodeContextBuilderImpl(context, template, path);
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) {
+ path.addNode(new NodeImpl(name));
+ return this;
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addPropertyNode(String name) {
+ final NodeImpl node = new NodeImpl.PropertyNodeImpl(name);
+ node.setKind(ElementKind.PROPERTY);
+ path.addNode(node);
+ return this;
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.LeafNodeBuilderCustomizableContext addBeanNode() {
+ final NodeImpl node = new NodeImpl.BeanNodeImpl();
+ node.setKind(ElementKind.BEAN);
+ path.addNode(node);
+ return new LeafNodeBuilderCustomizableContextImpl(context, template, path);
+ }
+
+ public ConstraintValidatorContext addConstraintViolation() {
+ context.addError(template, path);
+ return context;
+ }
+}
Added: bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java
URL: http://svn.apache.org/viewvc/bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java?rev=1517540&view=auto
==============================================================================
--- bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java (added)
+++ bval/branches/bval-11/bval-jsr/src/main/java/org/apache/bval/jsr/NodeContextBuilderImpl.java Mon Aug 26 13:59:15 2013
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.bval.jsr;
+
+import org.apache.bval.jsr.util.LeafNodeBuilderCustomizableContextImpl;
+import org.apache.bval.jsr.util.NodeBuilderDefinedContextImpl;
+import org.apache.bval.jsr.util.NodeImpl;
+import org.apache.bval.jsr.util.PathImpl;
+
+import javax.validation.ConstraintValidatorContext;
+import javax.validation.ElementKind;
+
+public class NodeContextBuilderImpl implements ConstraintValidatorContext.ConstraintViolationBuilder.NodeContextBuilder {
+ private final PathImpl path;
+ private final String template;
+ private final ConstraintValidatorContextImpl context;
+
+ public NodeContextBuilderImpl(final ConstraintValidatorContextImpl context, final String template, final PathImpl path) {
+ this.context = context;
+ this.template = template;
+ this.path = path;
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderDefinedContext atKey(Object key) {
+ path.getLeafNode().setKey(key);
+ return new NodeBuilderDefinedContextImpl(context, template, path);
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderDefinedContext atIndex(Integer index) {
+ path.getLeafNode().setIndex(index);
+ return new NodeBuilderDefinedContextImpl(context, template, path);
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) {
+ return new NodeBuilderCustomizableContextImpl(context, template, path).addNode(name);
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.NodeBuilderCustomizableContext addPropertyNode(String name) {
+ return new NodeBuilderCustomizableContextImpl(context, template, path).addPropertyNode(name);
+ }
+
+ public ConstraintValidatorContext.ConstraintViolationBuilder.LeafNodeBuilderCustomizableContext addBeanNode() {
+ final NodeImpl node = new NodeImpl.BeanNodeImpl();
+ node.setKind(ElementKind.BEAN);
+ path.addNode(node);
+ return new LeafNodeBuilderCustomizableContextImpl(context, template, path);
+ }
+
+ public ConstraintValidatorContext addConstraintViolation() {
+ context.addError(template, path);
+ return context;
+ }
+}