blob: 417b0cc91b42283e676f2e4d79bbdd145f676a92 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2014 Willink Transformations 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
*
* Contributors:
* E.D.Willink - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.labels;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.plugin.EcorePlugin;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.internal.labels.BooleanLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.DynamicEObjectImplLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.EAnnotationLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.EGenericTypeLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.ENamedElementLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.EObjectLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.EcoreURILabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.ElementIdLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.ExpressionInOCLLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.ModelLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.NameableLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.NumberLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.StringLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.TransformationInstanceLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.TypedModelInstanceLabelGenerator;
import org.eclipse.ocl.pivot.internal.labels.ValueLabelGenerator;
import org.eclipse.ocl.pivot.internal.plugin.LabelGeneratorRegistryReader;
import org.eclipse.ocl.pivot.labels.ILabelGenerator.Descriptor;
/**
* DebugString supports generation of debug identification of objects, determining a name usuing
* the following alternatives.
* <br>The null object is identified as <null-Object>
* <br>Implementers of IDebugString are identified by IDebugString.toDebugString();
* <br>MethodCall registrations in DebugUtils are identified by MethodCall.invoke().
* <br>Other objects are identified as <unknown-'class-name' 'object.toString()'>
* <p>
* MethodCall registrations may be made via registerInstanceMethod or registerStaticMethod.
* <p>
* A debug string may be obtained via DebugString.toDebug(object).
* <p>
* DebugString providers string formatters for simple classes such as String, Number, Boolean
* and Ecore components such as EObject, Resource and ResourceSet.
* <p>
* User extensions should be registered prior to use. Beware that late registration can
* give misleading results since in the absence of an exact MethodCall registration the
* class hierarchy is search first for base classes then for instances for which there
* is an exact MethodCall match. This result is then cached and so may occlude a late
* registration.
*/
public class LabelGeneratorRegistry implements ILabelGenerator.Registry
{
public static class Global extends LabelGeneratorRegistry
{
private boolean initialized = false;
public Global() {}
public void initialize() {
initialized = true;
if (EcorePlugin.IS_ECLIPSE_RUNNING) {
new LabelGeneratorRegistryReader(this).readRegistry();
}
else {
initialize(this);
}
}
@Override
public @Nullable ILabelGenerator<?> get(@NonNull Class<?> labelledClass) {
if (!initialized) {
initialize();
}
return super.get(labelledClass);
}
@Override
public @Nullable Object install(@NonNull Class<?> labelledClass, @NonNull Descriptor labelDescriptor) {
if (!initialized) {
initialize();
}
return super.install(labelledClass, labelDescriptor);
}
@Override
public @Nullable Object install(@NonNull Class<?> labelledClass, @NonNull ILabelGenerator<?> labelGenerator) {
if (!initialized) {
initialize();
}
return super.install(labelledClass, labelGenerator);
}
@Override
public void uninstall(@NonNull Class<?> labelledClass) {
if (!initialized) {
initialize();
}
super.uninstall(labelledClass);
}
}
public static @NonNull String debugLabelFor(@NonNull Object object) {
Map<ILabelGenerator.Option<?>, Object> options = new HashMap<ILabelGenerator.Option<?>, Object>();
options.put(ILabelGenerator.Builder.SHOW_CLASS_SIMPLE_NAME, Boolean.TRUE);
ILabelGenerator.Builder result = new DefaultLabelGeneratorBuilder(INSTANCE, object, options);
result.buildLabelFor(object);
return result.toString();
}
public static @NonNull LabelGeneratorRegistry init() {
return new LabelGeneratorRegistry.Global();
}
public static void initialize(@NonNull ILabelGenerator.Registry registry) {
BooleanLabelGenerator.initialize(registry);
DynamicEObjectImplLabelGenerator.initialize(registry);
EAnnotationLabelGenerator.initialize(registry);
EGenericTypeLabelGenerator.initialize(registry);
ENamedElementLabelGenerator.initialize(registry);
EObjectLabelGenerator.initialize(registry);
EcoreURILabelGenerator.initialize(registry);
ElementIdLabelGenerator.initialize(registry);
ExpressionInOCLLabelGenerator.initialize(registry);
ModelLabelGenerator.initialize(registry);
NameableLabelGenerator.initialize(registry);
NumberLabelGenerator.initialize(registry);
StringLabelGenerator.initialize(registry);
TransformationInstanceLabelGenerator.initialize(registry);
TypedModelInstanceLabelGenerator.initialize(registry);
ValueLabelGenerator.initialize(registry);
}
protected final @Nullable ILabelGenerator.Registry delegate;
private final @NonNull Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
/**
* Construct a registry that resolves label generators locally.
*/
private LabelGeneratorRegistry() {
this.delegate = null;
}
/**
* Construct a registry that resolves label generators locally when possible
* but which delegates to delegate otherwise.
*/
public LabelGeneratorRegistry(@Nullable ILabelGenerator.Registry delegate) {
this.delegate = delegate;
}
@Override
public <T> void buildLabelFor(@NonNull ILabelGenerator.Builder s, @Nullable T labelledObject) {
if (labelledObject == null) {
s.appendString("<null-Object>");
return;
}
Boolean showClassName = s.getOption(ILabelGenerator.Builder.SHOW_CLASS_NAME);
if ((showClassName != null) && (showClassName == Boolean.TRUE)) {
s.appendString(labelledObject.getClass().getName());
s.appendString(" ");
}
else {
Boolean showClassSimpleName = s.getOption(ILabelGenerator.Builder.SHOW_CLASS_SIMPLE_NAME);
if ((showClassSimpleName != null) && (showClassSimpleName == Boolean.TRUE)) {
s.appendString(labelledObject.getClass().getSimpleName());
s.appendString(" ");
}
}
if (labelledObject instanceof EObject) {
EObject eContainer = ((EObject)labelledObject).eContainer();
if (eContainer != null) {
String showQualifier = s.getOption(ILabelGenerator.Builder.SHOW_QUALIFIER);
if (showQualifier != null) {
buildLabelFor(s, eContainer);
if (s.toString().length() > 0) {
s.appendString(showQualifier);
}
}
}
}
if (labelledObject instanceof ILabelGenerator.Self) {
((ILabelGenerator.Self)labelledObject).buildLabel(s);
return;
}
buildSubLabelFor(s, labelledObject);
}
@Override
public <T> void buildSubLabelFor(@NonNull ILabelGenerator.Builder labelBuilder, @Nullable T labelledObject) {
if (labelledObject == null) {
labelBuilder.appendString("<null-Object>");
return;
}
@SuppressWarnings("null")@NonNull Class<? extends Object> labelledObjectClass = labelledObject.getClass();
ILabelGenerator<?> labelGenerator = get(labelledObjectClass);
if (labelGenerator == null) {
labelGenerator = getLabelGenerator(labelledObjectClass);
if (labelGenerator != null)
install(labelledObjectClass, labelGenerator);
}
if (labelGenerator != null) {
@SuppressWarnings("unchecked")
ILabelGenerator<T> castLabelGenerator = (ILabelGenerator<T>) labelGenerator;
castLabelGenerator.buildLabelFor(labelBuilder, labelledObject);
return;
}
else {
getLabelGenerator(labelledObjectClass); // Debugging
}
labelBuilder.appendString("<unknown-");
labelBuilder.appendString(labelledObjectClass.getSimpleName());
labelBuilder.appendString(" ");
labelBuilder.appendString(labelledObject.toString());
labelBuilder.appendString(">");
}
public @NonNull ILabelGenerator.Builder createDefaultLabelBuilder(@Nullable Object labelledObject, @Nullable Map<ILabelGenerator.Option<?>, Object> options) {
return new DefaultLabelGeneratorBuilder(this, labelledObject, options);
}
@Override
public @Nullable ILabelGenerator<?> get(@NonNull Class<?> labelledClass) {
Object object;
synchronized(map) {
object = map.get(labelledClass);
if (object instanceof ILabelGenerator.Descriptor) {
object = ((ILabelGenerator.Descriptor)object).getLabelGenerator();
map.put(labelledClass, object);
}
}
if (object != null) {
return (ILabelGenerator<?>)object;
}
else if (delegate != null) {
return delegate.get(labelledClass);
}
else {
return null;
}
}
protected @Nullable ILabelGenerator<?> getLabelGenerator(@NonNull Class<?> cls) {
for (Class<?> sCls = cls; sCls != null; sCls = sCls.getSuperclass()) {
ILabelGenerator<?> labelGenerator = get(sCls);
if (labelGenerator != null)
return labelGenerator;
}
for (@SuppressWarnings("null")@NonNull Class<?> iCls : cls.getInterfaces()) {
ILabelGenerator<?> labelGenerator = get(iCls);
if (labelGenerator != null)
return labelGenerator;
}
for (@SuppressWarnings("null")@NonNull Class<?> iCls : cls.getInterfaces()) {
ILabelGenerator<?> labelGenerator = getLabelGenerator(iCls);
if (labelGenerator != null)
return labelGenerator;
}
Class<?> sCls = cls.getSuperclass();
if (sCls != null)
return getLabelGenerator(sCls);
return null;
}
@Override
public @Nullable Object install(@NonNull Class<?> labelledClass, @NonNull Descriptor labelDescriptor) {
synchronized(map) {
return map.put(labelledClass, labelDescriptor);
}
}
@Override
public @Nullable Object install(@NonNull Class<?> labelledClass, @NonNull ILabelGenerator<?> labelGenerator) {
synchronized(map) {
return map.put(labelledClass, labelGenerator);
}
}
@Override
public @NonNull String labelFor(@Nullable Object labelledObject) {
ILabelGenerator.Builder labelBuilder = createDefaultLabelBuilder(labelledObject, null);
labelBuilder.buildLabelFor(labelledObject);
return labelBuilder.toString();
}
@Override
public @NonNull String labelFor(@Nullable Object labelledObject, @Nullable Map<ILabelGenerator.Option<?>, Object> options) {
ILabelGenerator.Builder labelBuilder = createDefaultLabelBuilder(labelledObject, options);
labelBuilder.buildLabelFor(labelledObject);
return labelBuilder.toString();
}
@Override
public void uninstall(@NonNull Class<?> labelledClass) {
synchronized(map) {
for (Class<?> aClass : new ArrayList<Class<?>>(map.keySet()))
{
if (labelledClass.isAssignableFrom(aClass)) {
map.remove(aClass);
}
}
}
}
}