001    /*******************************************************************************
002     * Portions created by Sebastian Thomschke are copyright (c) 2005-2011 Sebastian
003     * Thomschke.
004     * 
005     * All Rights Reserved. This program and the accompanying materials
006     * are made available under the terms of the Eclipse Public License v1.0
007     * which accompanies this distribution, and is available at
008     * http://www.eclipse.org/legal/epl-v10.html
009     * 
010     * Contributors:
011     *     Sebastian Thomschke - initial implementation.
012     *******************************************************************************/
013    package net.sf.oval.constraint;
014    
015    import static net.sf.oval.Validator.getCollectionFactory;
016    
017    import java.io.Serializable;
018    import java.lang.reflect.Constructor;
019    import java.util.Map;
020    
021    import net.sf.oval.Validator;
022    import net.sf.oval.configuration.annotation.AbstractAnnotationCheck;
023    import net.sf.oval.context.OValContext;
024    import net.sf.oval.exception.ReflectionException;
025    import net.sf.oval.internal.util.Assert;
026    
027    /**
028     * @author Sebastian Thomschke
029     */
030    public class CheckWithCheck extends AbstractAnnotationCheck<CheckWith>
031    {
032            public interface SimpleCheck extends Serializable
033            {
034                    boolean isSatisfied(Object validatedObject, Object value);
035            }
036    
037            public interface SimpleCheckWithMessageVariables extends SimpleCheck
038            {
039                    Map<String, ? extends Serializable> createMessageVariables();
040            }
041    
042            private static final long serialVersionUID = 1L;
043    
044            private boolean ignoreIfNull;
045            private SimpleCheck simpleCheck;
046    
047            /**
048             * {@inheritDoc}
049             */
050            @Override
051            public void configure(final CheckWith constraintAnnotation)
052            {
053                    super.configure(constraintAnnotation);
054                    setSimpleCheck(constraintAnnotation.value());
055                    setIgnoreIfNull(constraintAnnotation.ignoreIfNull());
056            }
057    
058            /**
059             * {@inheritDoc}
060             */
061            @Override
062            public Map<String, ? extends Serializable> createMessageVariables()
063            {
064                    final Map<String, Serializable> messageVariables = getCollectionFactory().createMap(4);
065    
066                    if (simpleCheck instanceof SimpleCheckWithMessageVariables)
067                    {
068                            final Map<String, ? extends Serializable> simpleCheckMessageVariables = ((SimpleCheckWithMessageVariables) simpleCheck)
069                                            .createMessageVariables();
070                            if (simpleCheckMessageVariables != null) messageVariables.putAll(simpleCheckMessageVariables);
071                    }
072                    messageVariables.put("ignoreIfNull", Boolean.toString(ignoreIfNull));
073                    messageVariables.put("simpleCheck", simpleCheck.getClass().getName());
074                    return messageVariables;
075            }
076    
077            /**
078             * @return the simpleCheck
079             */
080            public SimpleCheck getSimpleCheck()
081            {
082                    return simpleCheck;
083            }
084    
085            /**
086             * @return the ignoreIfNull
087             */
088            public boolean isIgnoreIfNull()
089            {
090                    return ignoreIfNull;
091            }
092    
093            /**
094             * {@inheritDoc}
095             */
096            public boolean isSatisfied(final Object validatedObject, final Object valueToValidate, final OValContext context,
097                            final Validator validator) throws ReflectionException
098            {
099                    if (valueToValidate == null && ignoreIfNull) return true;
100    
101                    return simpleCheck.isSatisfied(validatedObject, valueToValidate);
102            }
103    
104            /**
105             * @param ignoreIfNull the ignoreIfNull to set
106             */
107            public void setIgnoreIfNull(final boolean ignoreIfNull)
108            {
109                    this.ignoreIfNull = ignoreIfNull;
110                    requireMessageVariablesRecreation();
111            }
112    
113            /**
114             * @param simpleCheckType the simpleCheckType to set
115             * @throws IllegalArgumentException if <code>simpleCheckType == null</code>
116             */
117            public void setSimpleCheck(final Class< ? extends SimpleCheck> simpleCheckType) throws ReflectionException,
118                            IllegalArgumentException
119            {
120                    Assert.argumentNotNull("simpleCheckType", simpleCheckType);
121    
122                    try
123                    {
124                            final Constructor< ? extends SimpleCheck> ctor = simpleCheckType
125                                            .getDeclaredConstructor((Class< ? >[]) null);
126                            ctor.setAccessible(true);
127                            simpleCheck = ctor.newInstance();
128                    }
129                    catch (final Exception ex)
130                    {
131                            throw new ReflectionException("Cannot instantiate an object of type  " + simpleCheckType.getName(), ex);
132                    }
133                    requireMessageVariablesRecreation();
134            }
135    
136            /**
137             * @param simpleCheck the simpleCheck to set
138             * @throws IllegalArgumentException if <code>simpleCheck == null</code>
139             */
140            public void setSimpleCheck(final SimpleCheck simpleCheck) throws IllegalArgumentException
141            {
142                    Assert.argumentNotNull("simpleCheck", simpleCheck);
143    
144                    this.simpleCheck = simpleCheck;
145                    requireMessageVariablesRecreation();
146            }
147    }