/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG 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:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.internal.core.injector.extension;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.eclipse.riena.core.injector.extension.ExtensionInterface;
import org.eclipse.riena.core.util.Nop;
import org.eclipse.riena.core.util.StringUtils;
/**
* A extension point is in general a simple string. However, the extension
* injector supports multiple �compatible� extension point id's for a single
* �update� method. These id's will be treated as if they were one!.
* <p>
* Extension points are called �compatible� if the same
* {@code ExtensionInterface} can be used for both of them.
* <p>
* The objective here is to support a smooth and simple transition from
* @deprecated extension point id's to the new one.
*
* @since 1.2
*/
public class ExtensionPointId {
private final String rawId;
private List<String> normalizedIds;
private static final String DOT = "."; //$NON-NLS-1$
private static final String ID = "ID"; //$NON-NLS-1$
/**
* Create an undefined extension point id.
*/
public ExtensionPointId() {
this.rawId = null;
}
/**
* Create a �raw� extension point id.
*
* @param id
*/
public ExtensionPointId(final String id) {
this.rawId = id;
}
/**
* Normalize the extension point id.
* <p>
* This means:
* <ul>
* <li>splitting the �raw� extension point id separated by commas into
* separate id's</li>
* <li>retrieve id's if not specified from the {@code ExtensionInterface},
* i.e. from the annotation or by convention from a {@code String} field
* named {@code ID}.
* <li>transform simple id's to fully qualified id's</li>
* </ul>
*
* @param extensionInterface
*/
public void normalize(final Class<?> extensionInterface) {
if (normalizedIds != null) {
return;
}
normalizedIds = getNormalizedAndFullyQualifiedExtensionPointIds(extensionInterface);
}
/**
* Allows to iterate thru the compatible and normalized id's.
* <p>
* This requires that {@code normalize()} has been called before.
*
* @return
*/
public Iterable<String> compatibleIds() {
if (normalizedIds == null) {
throw new IllegalStateException("ExceptionPointId has not been normalized"); //$NON-NLS-1$
}
return normalizedIds;
}
/**
* Get the normalized and fully qualified extension point ids.
*
* @param extensionInterface
* @return
*/
private List<String> getNormalizedAndFullyQualifiedExtensionPointIds(final Class<?> extensionInterface) {
final List<String> ids = split(getRawExtensionPointId(rawId, extensionInterface));
final List<String> result = new ArrayList<String>(ids.size());
for (final String id : ids) {
if (id.contains(DOT)) {
// already a FQ id
result.add(id);
continue;
}
final Bundle bundle = FrameworkUtil.getBundle(extensionInterface);
if (bundle != null) {
result.add(bundle.getSymbolicName() + DOT + id);
continue;
}
// That might fail later!?
result.add(id);
}
return result;
}
/**
* Split the comma �,� separated string.
* <p>
* That could also be made wit {@code String.split()} but this
* implementation avoids creating a regExp and because of that it is a
* little bit faster.
*
* @param rawId
* @return
*/
private List<String> split(final String rawId) {
final List<String> result = new ArrayList<String>();
int fromIndex = 0;
int i;
while ((i = rawId.indexOf(',', fromIndex)) > 0) {
result.add(rawId.substring(fromIndex, i));
fromIndex = i + 1;
}
result.add(rawId.substring(fromIndex));
return result;
}
/**
* Since the extension point can be given via different ways, will retrieve
* it here.
*
* @param extensionInterface
* @param id
*/
private String getRawExtensionPointId(final String id, final Class<?> extensionInterface) {
if (StringUtils.isGiven(id)) {
return id;
}
final ExtensionInterface extensionInterfaceAnnotation = extensionInterface
.getAnnotation(ExtensionInterface.class);
if (extensionInterfaceAnnotation != null && StringUtils.isGiven(extensionInterfaceAnnotation.id())) {
return extensionInterfaceAnnotation.id();
}
try {
final Field idField = extensionInterface.getField(ID);
final Object value = idField.get(null);
if (value instanceof String) {
return (String) value;
}
} catch (final Exception e) {
Nop.reason("Fall throuh!"); //$NON-NLS-1$
}
throw new IllegalStateException(
"It was not possible to retrieve an extension point id from extension interface " + extensionInterface); //$NON-NLS-1$
}
@Override
public String toString() {
return "ExtensionPointId [normalizedIds=" + normalizedIds + ", rawId=" + rawId + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}