package org.sigmah.server.service.base;
/*
* #%L
* Sigmah
* %%
* Copyright (C) 2010 - 2016 URD
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.io.Serializable;
import java.util.Set;
import org.sigmah.server.dao.LocationTypeDAO;
import org.sigmah.server.dao.base.EntityManagerProvider;
import org.sigmah.server.domain.LocationType;
import org.sigmah.server.domain.User;
import org.sigmah.server.domain.UserDatabase;
import org.sigmah.server.domain.base.EntityId;
import org.sigmah.server.inject.util.Injectors;
import org.sigmah.server.mapper.Mapper;
import org.sigmah.shared.command.result.CreateResult;
import org.sigmah.shared.dispatch.CommandException;
import org.sigmah.shared.dto.base.EntityDTO;
import com.google.inject.Inject;
/**
* Abstract layer for entity services. Each {@link EntityService} implementation should inherit this class.
*
* @param <E>
* Entity type.
* @param <K>
* Entity id type.
* @param <D>
* Entity DTO type.
* @author Denis Colliot (dcolliot@ideia.fr)
*/
public abstract class AbstractEntityService<E extends EntityId<K>, K extends Serializable, D extends EntityDTO<K>> extends EntityManagerProvider
implements
EntityService<E, K, D> {
/**
* Entity class.
*/
protected final Class<E> entityClass;
/**
* Entity class.
*/
protected final Class<D> entityDTOClass;
/**
* Injected {@link LocationTypeDAO}.
*/
@Inject
private LocationTypeDAO locationTypeDAO;
/**
* Injected application mapper.
*/
@Inject
private Mapper mapper;
/**
* Service initialization.
*/
@SuppressWarnings("unchecked")
protected AbstractEntityService() {
this.entityClass = (Class<E>) Injectors.findGenericSuperClass(getClass()).getActualTypeArguments()[0];
this.entityDTOClass = (Class<D>) Injectors.findGenericSuperClass(getClass()).getActualTypeArguments()[2];
}
/**
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
@Override
public final <T extends EntityId<?>> CreateResult buildCreateResult(final T entity) throws CommandException {
if (entity != null && !(entity.getClass().equals(entityClass))) {
throw new IllegalArgumentException("Provided entity type '" + entity + "' does not match '" + entityClass.getName() + "' type.");
}
final EntityDTO<?> entityDTO;
if (entity == null || entityDTOClass == null || EntityDTO.class.equals(entityDTOClass)) {
entityDTO = new EntityDTO<K>() {
@Override
public K getId() {
return (K) entity.getId();
}
@Override
public String getEntityName() {
return entity.getClass().getSimpleName();
}
};
} else {
entityDTO = handleMapping((E) entity);
}
return new CreateResult(entityDTO);
}
/**
* Handles the given {@code entity} mapping to a proper DTO.<br>
* <em>Can be overridden by child implementations.</em>
*
* @param entity
* The created entity.
* @return The proper DTO instance.
*/
protected EntityDTO<?> handleMapping(final E entity) throws CommandException {
return mapper.map(entity, entityDTOClass);
}
/**
* Retrieves the <em>default</em> {@link LocationType} from the given {@code database} instance.<br>
* If no locationType cannot be found, a new <em>default</em> one is persisted.
*
* @param database
* The user database.
* @param user
* The user executing the action.
* @return The <em>default</em> {@link LocationType} instance (found or persisted).
*/
protected final LocationType locationTypeFromDatabase(final UserDatabase database, final User user) {
// Looking for 'default' locationType among database country's locations.
final Set<LocationType> locationTypes = database.getCountry().getLocationTypes();
for (final LocationType type : locationTypes) {
if (type.getName().equals(LocationType.DEFAULT)) {
return type;
}
}
// Still need to create the default location type for this country.
final LocationType defaultType = new LocationType();
defaultType.setName(LocationType.DEFAULT);
defaultType.setCountry(database.getCountry());
return locationTypeDAO.persist(defaultType, user);
}
}