/**
* Get more info at : www.jrebirth.org .
* Copyright JRebirth.org © 2011-2013
* Contact : sebastien.bordes@jrebirth.org
*
* Licensed 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.jrebirth.af.core.wave;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.jrebirth.af.api.command.Command;
import org.jrebirth.af.api.wave.Wave;
import org.jrebirth.af.api.wave.contract.WaveItem;
import org.jrebirth.af.api.wave.contract.WaveType;
import org.jrebirth.af.core.resource.provided.JRebirthParameters;
import org.jrebirth.af.core.util.ObjectUtility;
/**
* The class <strong>WaveType</strong>.
*
* @author Sébastien Bordes
*/
public final class WaveTypeBase implements WaveType {
/** The unique identifier of the wave type. */
private int uid;
/**
* The action to performed, basically the name of the method to call. The keyword "DO_" (by default see {@link JRebirthParameters.WAVE_HANDLER_PREFIX}) will be prepended to the action name to
* generate the handler method
*/
private String action;
/** Define arguments types to use. */
private final List<WaveItem<?>> waveItemList = new ArrayList<>();
/** The action called after, basically the name of the method to call. */
private String returnAction;
/** Define returned value type (if any). */
private WaveItem<?> returnItem;
/** The wave type of the wave returned after processing. */
private WaveType returnWaveType;
/** The command to call to process the returned value. */
private Class<? extends Command> returnCommandClass;
private Map<Class<? extends Throwable>, Wave> waveExceptionHanler;
// public static WaveTypeBase create() {
// return new WaveTypeBase();
// }
//
// /**
// * Build a wave type.
// *
// * @param action The action to perform, "DO_" keyword (by default see {@link JRebirthParameters.WAVE_HANDLER_PREFIX}) will be prepended to the action name to generate the handler method
// *
// * @param waveItems the list of {@link WaveItem} required by this wave
// *
// * @return a new fresh wave type object
// */
// public static WaveTypeBase create(final String action/* , final WaveItem<?>... waveItems */) {
//
// return Builders.waveType().action(action/* , waveItems */);
// }
/**
* Default constructor.
*/
WaveTypeBase() {
// Ensure that the uid will be unique at runtime
uid(WaveTypeRegistry.getNextUid());
}
/**
* {@inheritDoc}
*/
@Override
public int uid() {
return this.uid;
}
/**
* {@inheritDoc}
*/
@Override
public WaveTypeBase uid(final int uid) {
this.uid = uid;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public String action() {
return this.action;
}
/**
* {@inheritDoc}
*/
@Override
public WaveTypeBase action(final String action) {
WaveTypeRegistry.store(action, this);
this.action = action;
return this;
}
/**
* {@inheritDoc}
*/
@Override
public List<WaveItem<?>> items() {
return this.waveItemList;
}
/**
* {@inheritDoc}
*/
@Override
public WaveTypeBase items(final WaveItem<?>... items) {
// Add each wave item to manage method argument
for (final WaveItem<?> waveItem : items) {
this.waveItemList.add(waveItem);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public String returnAction() {
return this.returnAction;
}
/**
* {@inheritDoc}
*/
@Override
public WaveTypeBase returnAction(final String returnAction) {
this.returnAction = returnAction;
buildReturnWaveType();
return this;
}
/**
* {@inheritDoc}
*/
@Override
public WaveItem<?> returnItem() {
return this.returnItem;
}
/**
* {@inheritDoc}
*/
@Override
public WaveTypeBase returnItem(final WaveItem<?> returnItem) {
this.returnItem = returnItem;
buildReturnWaveType();
return this;
}
private void buildReturnWaveType() {
if (this.returnAction != null && this.returnItem != null) {
this.returnWaveType = Builders.waveType(this.returnAction).items(returnItem());
}
}
/**
* {@inheritDoc}
*/
@Override
public WaveType returnWaveType() {
return this.returnWaveType;
}
/**
* {@inheritDoc}
*/
@Override
public WaveType returnWaveType(final WaveType returnWaveType) {
this.returnWaveType = returnWaveType;
this.returnAction = returnWaveType.action();
this.returnItem = returnWaveType.items().stream().findFirst().orElse(null);
return this;
}
/**
* Return the required method parameter list to handle this WaveType.
*
* @return the parameter list (Type1 arg1, Type2 arg2 ...)
*/
public String getItems() {
final StringBuilder sb = new StringBuilder();
boolean first = true;
for (final WaveItem<?> waveItem : items()) {
if (first) {
first = false;
} else {
sb.append(", ");
}
String fullName = waveItem.getItemType() instanceof ParameterizedType ? ((ParameterizedType) waveItem.getItemType()).toString()
: ((Class<?>) waveItem.getItemType()).getName();
sb.append(fullName).append(" ");
fullName = fullName.replaceAll("[<>]", "");
if (waveItem.getName() == null || waveItem.getName().isEmpty()) {
sb.append(ObjectUtility.lowerFirstChar(fullName.substring(fullName.lastIndexOf('.') + 1)));
} else {
sb.append(waveItem.getName());
}
}
return sb.toString();
}
// /**
// * Gets the return wave type.
// *
// * @return the return wave type
// */
// public WaveType getReturnWaveType() {
// return this.returnWaveType;
// }
//
// /**
// * Sets the return wave type.
// *
// * @param returnWaveType the new return wave type
// */
// public void setReturnWaveType(final WaveType returnWaveType) {
// this.returnWaveType = returnWaveType;
// }
/**
* {@inheritDoc}
*/
@Override
public String toString() {
// The action name will be used to define the name of the wave handler method
// Prepend do before the action name to force wave handler method to begin with do (convention parameterizable)
return JRebirthParameters.WAVE_HANDLER_PREFIX.get() + this.action;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(final Object waveType) {
return waveType instanceof WaveTypeBase && uid() == ((WaveTypeBase) waveType).uid();
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return uid();
}
/**
* {@inheritDoc}
*/
@Override
public Class<? extends Command> returnCommandClass() {
return this.returnCommandClass;
}
/**
* {@inheritDoc}
*/
@Override
public WaveType returnCommandClass(final Class<? extends Command> returnCommandClass) {
this.returnCommandClass = returnCommandClass;
return this;
}
@Override
public List<WaveItem<?>> parameters() {
return items().stream().filter(item -> item.isParameter()).collect(Collectors.toList());
}
/**
* {@inheritDoc}
*/
@Override
public Map<Class<? extends Throwable>, Wave> waveExceptionHanler() {
if (this.waveExceptionHanler == null) {
this.waveExceptionHanler = new ConcurrentHashMap<>();
}
return this.waveExceptionHanler;
}
/**
* {@inheritDoc}
*/
@Override
public WaveType onException(final Class<? extends Command> exceptionCommandClass, final Class<? extends Throwable>... exceptionTypes) {
final Wave commandWave = Builders.callCommand(exceptionCommandClass);
for (final Class<? extends Throwable> type : exceptionTypes) {
waveExceptionHanler().put(type, commandWave);
}
return this;
}
/**
* {@inheritDoc}
*/
@Override
public WaveType onException(final WaveType exceptionWaveType, final Class<? extends Throwable>... exceptionTypes) {
final Wave wave = Builders.wave().waveType(exceptionWaveType);
for (final Class<? extends Throwable> type : exceptionTypes) {
waveExceptionHanler().put(type, wave);
}
return this;
}
}