/*
* 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.myfaces.extensions.cdi.message.api;
import org.apache.myfaces.extensions.cdi.message.api.payload.MessagePayload;
import org.apache.myfaces.extensions.cdi.message.api.payload.MessagePayloadKey;
import java.io.Serializable;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
/**
* @author Gerhard Petracek
*/
public abstract class AbstractMessage implements Message, MessageContextConfigAware<Message>
{
protected String messageDescriptor;
protected Set<NamedArgument> namedArguments = new HashSet<NamedArgument>();
protected List<Serializable> arguments = new ArrayList<Serializable>();
protected Map<Class, MessagePayload> messagePayload = new HashMap<Class, MessagePayload>();
//optional
@Deprecated
//currently not used - would be useful for messages which are aware of the original context they were created in
private MessageContextConfig messageContextConfig;
public AbstractMessage(Message message)
{
this(message.getDescriptor(), message.getArguments());
this.messagePayload = message.getPayload();
}
public AbstractMessage(String messageDescriptor, Serializable... arguments)
{
this.messageDescriptor = messageDescriptor;
for (Serializable argument : arguments)
{
if (argument instanceof MessagePayload)
{
//TODO log warning
//noinspection unchecked
addPayload((MessagePayload) argument);
}
else
{
addArgument(argument);
}
}
cleanup();
}
public AbstractMessage(String messageDescriptor, Set<NamedArgument> namedArguments)
{
this.messageDescriptor = messageDescriptor;
this.namedArguments = namedArguments;
this.arguments = null;
}
public void addArgument(Serializable... arguments)
{
for (Serializable argument : arguments)
{
if(argument == null)
{
argument = "null";
}
if(isHiddenArgument(argument))
{
addHiddenArgument(argument);
}
else
{
addArgumentToMessage(argument);
}
}
}
private void addArgumentToMessage(Object argument)
{
Serializable result;
if(argument instanceof Serializable)
{
result = (Serializable)argument;
}
else
{
result = processNoneSerializableArgument(argument);
}
checkArgument(result);
if (argument instanceof NamedArgument)
{
addNamedArgument((NamedArgument) argument);
}
else
{
addNumberedArgument(result);
}
}
/**
* if the argument isn't serializable we aren't allowed to store the instance itself
* -> we have to store the string instead
* (if we are aware of the context and the parameter implements {@link Localizable} we use the localized value)
*
* @param argument current argument
* @return the string value of the argument
*/
private String processNoneSerializableArgument(Object argument)
{
if(argument instanceof Localizable && this.getMessageContextConfig() != null)
{
return ((Localizable)argument).toString(this.getMessageContextConfig().use().create());
}
else
{
return argument != null ? argument.toString() : "null";
}
}
private boolean isHiddenArgument(Serializable argument)
{
return argument != null && argument.getClass().isArray();
}
private void addHiddenArgument(Serializable argument)
{
for(Object current : ((Object[])argument))
{
addArgumentToMessage(current);
}
}
private void checkArgument(Serializable argument)
{
if (argument instanceof NamedArgument)
{
//noinspection SuspiciousMethodCalls
if (this.namedArguments != null)
{
for (NamedArgument namedArgument : this.namedArguments)
{
if (namedArgument.getName().equals(((NamedArgument) argument).getName()))
{
throw new UnsupportedOperationException(
"it isn't allowed to override arguments - argument name: " +
((NamedArgument) argument).getName());
}
}
}
}
}
protected void addNamedArgument(NamedArgument namedArgument)
{
if (this.namedArguments == null)
{
this.namedArguments = new HashSet<NamedArgument>();
}
this.namedArguments.add(namedArgument);
}
protected void addNumberedArgument(Serializable argument)
{
if (this.arguments == null)
{
this.arguments = new ArrayList<Serializable>();
}
this.arguments.add(argument);
}
public String getDescriptor()
{
return this.messageDescriptor;
}
public Serializable[] getArguments()
{
if (this.namedArguments == null && this.arguments == null)
{
return new Serializable[]{};
}
if (this.namedArguments == null)
{
return this.arguments.toArray(new Serializable[this.arguments.size()]);
}
else if (this.arguments == null)
{
return this.namedArguments.toArray(new Serializable[this.namedArguments.size()]);
}
List<Serializable> mergedArguments =
new ArrayList<Serializable>(this.namedArguments.size() + this.arguments.size());
mergedArguments.addAll(this.namedArguments);
mergedArguments.addAll(this.arguments);
return mergedArguments.toArray(new Serializable[mergedArguments.size()]);
}
public void addPayload(MessagePayload payload)
{
Class key = payload.getClass();
if (payload.getClass().isAnnotationPresent(MessagePayloadKey.class))
{
key = payload.getClass().getAnnotation(MessagePayloadKey.class).value();
}
addPayload(key, payload);
}
public Map<Class, MessagePayload> getPayload()
{
return Collections.unmodifiableMap(this.messagePayload);
}
public void addPayload(Class key, MessagePayload payload)
{
if (this.messagePayload.containsKey(key))
{
throw new UnsupportedOperationException("it isn't allowed to override payload - key: " + key.getName());
}
this.messagePayload.put(key, payload);
}
public Message setMessageContextConfig(MessageContextConfig messageContextConfig)
{
this.messageContextConfig = messageContextConfig;
return this;
}
public MessageContextConfig getMessageContextConfig()
{
return this.messageContextConfig;
}
private void cleanup()
{
if (this.namedArguments != null && this.namedArguments.isEmpty())
{
this.namedArguments = null;
}
if (this.arguments != null && this.arguments.isEmpty())
{
this.arguments = null;
}
}
/*
* generated
*/
@Override
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (!(o instanceof AbstractMessage))
{
return false;
}
AbstractMessage that = (AbstractMessage) o;
if (messagePayload != null ? !messagePayload.equals(that.messagePayload) : that.messagePayload != null)
{
return false;
}
if (!messageDescriptor.equals(that.messageDescriptor))
{
return false;
}
if (namedArguments != null ? !namedArguments.equals(that.namedArguments) : that.namedArguments != null)
{
return false;
}
//noinspection RedundantIfStatement
if (arguments != null ? !arguments.equals(that.arguments) : that.arguments != null)
{
return false;
}
return true;
}
@Override
public int hashCode()
{
int result = messageDescriptor.hashCode();
result = 31 * result + (namedArguments != null ? namedArguments.hashCode() : 0);
result = 31 * result + (arguments != null ? arguments.hashCode() : 0);
result = 31 * result + (messagePayload != null ? messagePayload.hashCode() : 0);
return result;
}
}