/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.eclipse.emf.ecore.xcore.tests;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
/**
* @author Moritz Eysholdt - Initial contribution and API
*
* TODO: move this to xtext.util
*/
public class EObjectFormatter implements Function<EObject, String>
{
protected boolean resolveCrossReferences = false;
protected boolean showIndex = false;
public String apply(EObject from)
{
return format(from);
}
protected String assignmentOperator(EObject object, EStructuralFeature feature)
{
if (feature instanceof EReference && !((EReference) feature).isContainment())
return "->";
else
return "=";
}
public String format(EObject object)
{
if (object == null)
return "null";
StringBuilder result = new StringBuilder();
result.append(object.eClass().getName());
result.append(" {");
for (EStructuralFeature feature : object.eClass().getEAllStructuralFeatures())
if (shouldFormat(object, feature))
result.append(indent("\n" + format(object, feature)));
result.append("\n}");
return result.toString();
}
protected String format(EObject object, EStructuralFeature feature)
{
StringBuilder result = new StringBuilder();
result.append(feature.getName());
result.append(" ");
result.append(assignmentOperator(object, feature));
result.append(" ");
Object val = object.eGet(feature, resolveCrossReferences);
if (feature.isMany())
{
result.append("[");
List<?> vals = (List<?>) val;
List<?> sortedVals = sort(object, feature, vals);
if (vals == sortedVals)
{
for (int i = 0; i < vals.size(); i++)
if (shouldFormat(object, feature, i, vals.get(i)))
result.append(indent("\n" + format(object, feature, i, vals.get(i))));
} else
{
for (int i = 0; i < sortedVals.size(); i++)
if (shouldFormat(object, feature, sortedVals.get(i)))
result.append(indent("\n" + format(object, feature, sortedVals.get(i))));
}
result.append("\n]");
} else
result.append(indent(format(object, feature, val)));
return result.toString();
}
protected String format(EObject object, EStructuralFeature feature, int index, Object value)
{
if (showIndex)
return index + ": " + format(object, feature, value);
return format(object, feature, value);
}
protected String format(EObject object, EStructuralFeature feature, Object value)
{
if (feature instanceof EAttribute)
return formatAttributeValue(object, (EAttribute) feature, value);
else if (feature instanceof EReference)
{
EReference ref = (EReference) feature;
if (ref.isContainment())
return format((EObject) value);
return formatCrossRefValue(object, ref, (EObject) value);
}
return "";
}
public String format(Iterable<? extends EObject> object)
{
return Joiner.on('\n').join(Iterables.transform(object, this));
}
protected String formatAttributeValue(EObject object, EAttribute feature, Object value)
{
if (value == null)
return "null";
EFactory factory = feature.getEAttributeType().getEPackage().getEFactoryInstance();
String stringVal = factory.convertToString(feature.getEAttributeType(), value);
return "'" + stringVal + "'";
}
protected String formatCrossRefValue(EObject object, EReference feature, EObject value)
{
if (value == null)
return "null";
if (value.eIsProxy())
return "proxy (URI: " + ((InternalEObject) value).eProxyURI() + ")";
if (value.eResource() == object.eResource())
return value.eClass().getName() + " " + object.eResource().getURIFragment(value);
URI uri = EcoreUtil.getURI(value);
uri = uri.deresolve(object.eResource().getURI());
return value.eClass().getName() + " " + uri.toString();
}
protected String indent(String string)
{
return string.replaceAll("\\n", "\n\t");
}
public EObjectFormatter resolveCrossReferences()
{
this.resolveCrossReferences = true;
return this;
}
protected boolean shouldFormat(EObject object, EStructuralFeature feature)
{
if (feature.isDerived())
return false;
if (feature instanceof EReference && ((EReference) feature).isContainer())
return false;
return object.eIsSet(feature);
}
protected boolean shouldFormat(EObject object, EStructuralFeature feature, int index, Object value)
{
return true;
}
protected boolean shouldFormat(EObject object, EStructuralFeature feature, Object value)
{
return true;
}
public EObjectFormatter showIndex()
{
this.showIndex = true;
return this;
}
protected List<?> sort(EObject obj, EStructuralFeature feature, List<?> values)
{
return values;
}
}