001package org.andromda.core.metafacade;
002
003import java.io.Serializable;
004import java.util.List;
005import org.andromda.core.common.ClassUtils;
006import org.andromda.core.common.ExceptionUtils;
007import org.apache.commons.lang.StringUtils;
008
009/**
010 * Stores the validation messages that are collected during model validation.
011 *
012 * @author Chad Brandon
013 */
014public class ModelValidationMessage
015    implements Serializable
016{
017    private static final long serialVersionUID = 34L;
018
019    /**
020     * Constructs a new instance of MetafacadeValidationMessage taking a
021     * <code>metafacade</code> instance and a <code>message</code>
022     * indicating what has been violated.
023     *
024     * @param metafacade the metafacade being validated.
025     * @param message the message to to communicate about the validation.
026     */
027    public ModelValidationMessage(
028        final MetafacadeBase metafacade,
029        final String message)
030    {
031        this(metafacade, null, message);
032    }
033
034    /**
035     * Constructs a new instance of MetafacadeValidationMessage taking a
036     * <code>metafacade</code> instance the <code>name</code> of the
037     * validation constraint and the actual <code>message</code> text indicating
038     * what has been violated.
039     *
040     * @param metafacade the metafacade being validated.
041     * @param name the name of the model element being validated.
042     * @param message the message to communicate about the validation.
043     */
044    public ModelValidationMessage(
045        final MetafacadeBase metafacade,
046        final String name,
047        final String message)
048    {
049        ExceptionUtils.checkNull("metafacade", metafacade);
050        ExceptionUtils.checkEmpty("message", message);
051        this.metafacade = metafacade;
052        this.name = name;
053        this.message = message;
054    }
055
056    /**
057     * Stores the actual name of the constraint (if there is one).
058     */
059    private String name;
060
061    /**
062     * Gets the name of the validation constraint.
063     *
064     * @return the constraint name.
065     */
066    public String getName()
067    {
068        return this.name;
069    }
070
071    /**
072     * Stores the actual message text.
073     */
074    private String message;
075
076    /**
077     * Gets the actual message text.
078     *
079     * @return Returns the message.
080     */
081    public String getMessage()
082    {
083        return message;
084    }
085
086    /**
087     * Stores the actual metafacade to which this validation message applies.
088     */
089    private MetafacadeBase metafacade;
090
091    /**
092     * Stores the metafacade name which is only constructed the very first time.
093     */
094    private String metafacadeName = null;
095
096    /**
097     * Gets the name of the metafacade to which this validation message applies.
098     *
099     * @return Returns the metafacade.
100     */
101    public String getMetafacadeName()
102    {
103        if (this.metafacadeName == null)
104        {
105            final String separator = MetafacadeConstants.NAMESPACE_SCOPE_OPERATOR;
106            final StringBuilder name = new StringBuilder();
107            for (
108                MetafacadeBase metafacade = this.metafacade; metafacade != null;
109                metafacade = (MetafacadeBase)metafacade.getValidationOwner())
110            {
111                if (StringUtils.isNotBlank(metafacade.getValidationName()))
112                {
113                    String validationName = metafacade.getValidationName();
114                    if (metafacade.getValidationOwner() != null)
115                    {
116                        // remove package if we have an owner
117                        validationName = validationName.replaceAll(".*" + separator, "");
118                    }
119                    if (name.length()>0)
120                    {
121                        name.insert(0, separator);
122                    }
123                    name.insert(0, validationName);
124                }
125            }
126            this.metafacadeName = name.toString();
127        }
128        return metafacadeName;
129    }
130
131    /**
132     * Stores the metafacade class displayed within the message, this is only retrieved the very first time.
133     */
134    private Class metafacadeClass = null;
135
136    /**
137     * Gets the class of the metafacade to which this validation message applies.
138     *
139     * @return the metafacade Class.
140     */
141    public Class getMetafacadeClass()
142    {
143        if (metafacadeClass == null)
144        {
145            this.metafacadeClass = this.metafacade.getClass();
146            final List interfaces = ClassUtils.getAllInterfaces(this.metafacade.getClass());
147            if (interfaces != null && !interfaces.isEmpty())
148            {
149                this.metafacadeClass = (Class)interfaces.iterator().next();
150            }
151        }
152        return this.metafacadeClass;
153    }
154
155    /**
156     * @see Object#toString()
157     */
158    public String toString()
159    {
160        final StringBuilder toString = new StringBuilder();
161        toString.append('[');
162        toString.append(this.getMetafacadeName());
163        toString.append(']');
164        toString.append(':');
165        toString.append(this.message);
166        return toString.toString();
167    }
168
169    /**
170     * @see Object#hashCode()
171     */
172    public int hashCode()
173    {
174        return this.toString().hashCode();
175    }
176
177    /**
178     * @see Object#equals(Object)
179     */
180    @SuppressWarnings("null") // Compiler doesn't not recognize that object cannot be null when using message
181    public boolean equals(Object object)
182    {
183        boolean equals = object != null && ModelValidationMessage.class == object.getClass();
184        if (equals)
185        {
186            final ModelValidationMessage message = (ModelValidationMessage)object;
187            // message can never be null at this point, because object cannot be null, despite the compiler warning
188            if (message != null)
189            {
190                equals = message.toString().equals(this.toString());
191            }
192        }
193        return equals;
194    }
195}