/**
* eAdventure (formerly <e-Adventure> and <e-Game>) is a research project of the
* <e-UCM> research group.
*
* Copyright 2005-2010 <e-UCM> research group.
*
* You can access a list of all the contributors to eAdventure at:
* http://e-adventure.e-ucm.es/contributors
*
* <e-UCM> is a research group of the Department of Software Engineering
* and Artificial Intelligence at the Complutense University of Madrid
* (School of Computer Science).
*
* C Profesor Jose Garcia Santesmases sn,
* 28040 Madrid (Madrid), Spain.
*
* For more info please visit: <http://e-adventure.e-ucm.es> or
* <http://www.e-ucm.es>
*
* ****************************************************************************
*
* This file is part of eAdventure, version 2.0
*
* eAdventure is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* eAdventure 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with eAdventure. If not, see <http://www.gnu.org/licenses/>.
*/
package es.eucm.ead.writer.model.writers.simplifiers;
import es.eucm.ead.model.assets.drawable.basics.EAdShape;
import es.eucm.ead.model.assets.drawable.basics.Image;
import es.eucm.ead.model.assets.drawable.basics.animation.FramesAnimation;
import es.eucm.ead.model.assets.drawable.compounds.StateDrawable;
import es.eucm.ead.model.elements.BasicElement;
import es.eucm.ead.model.elements.conditions.Condition;
import es.eucm.ead.model.elements.operations.ElementField;
import es.eucm.ead.model.elements.operations.Operation;
import es.eucm.ead.model.elements.scenes.SceneElement;
import es.eucm.ead.model.elements.scenes.SceneElementDef;
import es.eucm.ead.tools.EAdUtils;
import es.eucm.ead.tools.reflection.ReflectionClass;
import es.eucm.ead.tools.reflection.ReflectionClassLoader;
import es.eucm.ead.writer.model.writers.simplifiers.assets.FramesAnimationSimplifier;
import es.eucm.ead.writer.model.writers.simplifiers.assets.ImagesSimplifier;
import es.eucm.ead.writer.model.writers.simplifiers.assets.ShapesSimplifier;
import es.eucm.ead.writer.model.writers.simplifiers.assets.StateDrawablesSimplifier;
import es.eucm.ead.writer.model.writers.simplifiers.elements.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Simplifier {
static private Logger logger = LoggerFactory.getLogger(Simplifier.class);
private Map<Class<?>, List<Object>> objectsLists;
private Map<Class<?>, ObjectSimplifier<?>> simplifiers;
private int simplifications;
private FieldsSimplifier fieldsSimplifier;
public Simplifier() {
objectsLists = new HashMap<Class<?>, List<Object>>();
simplifications = 0;
simplifiers = new HashMap<Class<?>, ObjectSimplifier<?>>();
// Simplifiers
fieldsSimplifier = new FieldsSimplifier();
simplifiers.put(Condition.class, new ConditionsSimplifier());
simplifiers.put(ElementField.class, fieldsSimplifier);
simplifiers.put(Operation.class, new OperationsSimplifier());
simplifiers.put(SceneElementDef.class, new SceneElementDefSimplifier());
simplifiers.put(FramesAnimation.class, new FramesAnimationSimplifier());
simplifiers.put(Image.class, new ImagesSimplifier());
simplifiers.put(EAdShape.class, new ShapesSimplifier());
simplifiers.put(StateDrawable.class, new StateDrawablesSimplifier());
}
public void clear() {
simplifications = 0;
objectsLists.clear();
for (ObjectSimplifier<?> o : simplifiers.values()) {
o.clear();
}
fieldsSimplifier.clear();
}
public Object simplify(Object o) {
Object oldObject = o;
if (o instanceof SceneElement || o.getClass() == BasicElement.class) {
// SceneElement can not be simplified
// BaiscElement are already simplified
return o;
}
Class<?> oldClass = o.getClass();
Class<?> newClass = null;
while (oldClass != newClass) {
Object newObject = simplifyImpl(o);
if (newObject == null) {
logger.warn("Error simplifiying asset: {}", o);
return null;
}
newClass = newObject.getClass();
oldClass = o.getClass();
o = newObject;
}
List<Object> list = objectsLists.get(o.getClass());
if (list == null) {
list = new ArrayList<Object>();
objectsLists.put(o.getClass(), list);
}
o = simplifyCheckEquals(o, list, generalEq);
if (oldObject != o) {
simplifications++;
}
return o;
}
@SuppressWarnings( { "rawtypes", "unchecked" })
public Object simplifyImpl(Object o) {
ReflectionClass<?> clazz = ReflectionClassLoader.getReflectionClass(o
.getClass());
while (clazz != null) {
ObjectSimplifier simplifier = simplifiers.get(clazz.getType());
if (simplifier != null) {
o = simplifier.simplify(o);
}
for (ReflectionClass<?> i : clazz.getInterfaces()) {
simplifier = simplifiers.get(i.getType());
if (simplifier != null) {
o = simplifier.simplify(o);
}
}
clazz = clazz.getSuperclass();
}
return o;
}
public int getSimplifications() {
return simplifications;
}
public interface CheckEquals<T> {
boolean equals(T o1, T o2);
}
private CheckEquals<Object> generalEq = new CheckEquals<Object>() {
@Override
public boolean equals(Object o1, Object o2) {
if (o1 == o2) {
return true;
}
boolean equals = EAdUtils.equals(o1, o2, true);
return equals;
}
};
private Object simplifyCheckEquals(Object o, List<Object> list,
CheckEquals<Object> generalEq2) {
Object copy = find(o, list, generalEq2);
if (copy == null) {
copy = o;
list.add(o);
} else {
simplifications++;
}
return copy;
}
public Object find(Object o2, List<Object> list,
CheckEquals<Object> generalEq2) {
for (Object o : list) {
if (generalEq2.equals(o2, o)) {
return o;
}
}
return null;
}
public Map<Object, Map<String, ElementField>> getFields() {
return fieldsSimplifier.getFields();
}
public Map<Class<?>, List<Object>> getIdentified() {
return objectsLists;
}
}