package fr.openwide.core.jpa.more.business.history.service; import java.util.Locale; import org.springframework.beans.factory.annotation.Autowired; import com.google.common.base.Optional; import fr.openwide.core.commons.util.rendering.IRenderer; import fr.openwide.core.jpa.business.generic.model.GenericEntity; import fr.openwide.core.jpa.business.generic.model.GenericEntityReference; import fr.openwide.core.jpa.business.generic.service.IEntityService; import fr.openwide.core.jpa.more.business.history.model.embeddable.HistoryEntityReference; import fr.openwide.core.jpa.more.business.history.model.embeddable.HistoryValue; import fr.openwide.core.jpa.more.rendering.service.IRendererService; import fr.openwide.core.jpa.util.HibernateUtils; import fr.openwide.core.spring.property.SpringPropertyIds; import fr.openwide.core.spring.property.service.IPropertyService; public abstract class AbstractHistoryValueServiceImpl implements IHistoryValueService { @Autowired protected IEntityService entityService; @Autowired protected IRendererService rendererService; @Autowired protected IPropertyService propertyService; /* * Even if object.getClass() is a subtype of T (say T2), this will work. * * The returned renderer will actually be of type IRenderer<? super T2>. * This is enough to allow calling renderer.render(object) at runtime, even though at * compile time, it's a bit dodgy. Maybe we could write something like object.getClass().cast(object) * just to get the right type, but it would seem a little dumb... */ @SuppressWarnings("unchecked") @Override public final <T> HistoryValue create(T object) { if (object == null) { return new HistoryValue(); } else { @SuppressWarnings("rawtypes") IRenderer renderer = rendererService.findRenderer(object.getClass()); return create(object, renderer); } } @Override public final <T> HistoryValue create(T value, IRenderer<? super T> renderer) { String label = renderer.render(value, propertyService.get(SpringPropertyIds.DEFAULT_LOCALE)); if (value instanceof GenericEntity) { GenericEntity<?, ?> entity = (GenericEntity<?, ?>) value; if (entity.getId() instanceof Long) { @SuppressWarnings("unchecked") GenericEntityReference<Long, ?> reference = GenericEntityReference.of((GenericEntity<Long, ?>)entity); return new HistoryValue(label, reference); } } String serialized = serialize(value); return new HistoryValue(label, serialized); } protected String serialize(Object value) { if (value instanceof Enum) { return ((Enum<?>) value).name(); } return null; } protected Object deserialize(String value) { return null; // Can't do a thing with the default implementation of serialize(Object) } @Override public final Object retrieve(HistoryValue value) { if (value == null) { return null; } HistoryEntityReference reference = value.getReference(); if (reference != null && reference.getType() != null && reference.getId() != null) { return entityService.getEntity(reference); } return deserialize(value.getSerialized()); } @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public final String render(HistoryValue value, IRenderer renderer, Locale locale) { if (value == null) { return null; } if (renderer != null) { Object retrieved = retrieve(value); if (retrieved != null) { return renderer.render(retrieved, locale); } } return value.getLabel(); } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public final String render(HistoryValue value, Locale locale) { if (value == null) { return null; } Object retrieved = retrieve(value); if (retrieved != null) { IRenderer renderer = rendererService.findRenderer(HibernateUtils.getClass(retrieved)); return renderer.render(retrieved, locale); } return value.getLabel(); } @Override public Optional<Boolean> matches(HistoryValue historyValue, Object value) { if (historyValue == null) { // We never return null from create(...). Thus a null HistoryValue does not match anything. return Optional.of(false); } GenericEntityReference<Long, ?> referenceReference = historyValue.getReference(); if (referenceReference != null) { if (!(value instanceof GenericEntity)) { return Optional.of(false); } GenericEntityReference<?, ?> candidateReference = GenericEntityReference.of((GenericEntity<?, ?>)value); return Optional.of(referenceReference.equals(candidateReference)); } // Don't know return Optional.absent(); } }