blob: da41ed73a3b2d09ad5e50657096bc0b49b7ae2a9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.acceleo.query.runtime.impl;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.eclipse.acceleo.query.runtime.AcceleoQueryEvaluationException;
import org.eclipse.acceleo.query.runtime.ICompletionProposal;
import org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment;
import org.eclipse.acceleo.query.runtime.IService;
import org.eclipse.acceleo.query.validation.type.IType;
import org.eclipse.emf.ecore.EClass;
/**
* Abstract implementation of {@link IService}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public abstract class AbstractService<O> implements IService<O> {
/**
* The {@link O origin} of this service.
*/
private final O origin;
/**
* Constructor with an {@link Object origin}.
*
* @param serviceOrigin
* the (maybe {@code null}) {@link Object origin} of this service.
*/
protected AbstractService(O serviceOrigin) {
this.origin = serviceOrigin;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#getOrigin()
*/
@Override
public O getOrigin() {
return this.origin;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#isEqualParameterTypes(org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment,
* org.eclipse.acceleo.query.runtime.IService)
*/
@Override
public boolean isEqualParameterTypes(IReadOnlyQueryEnvironment queryEnvironment, IService<?> service) {
final List<IType> paramTypes1 = getParameterTypes(queryEnvironment);
final List<IType> paramTypes2 = service.getParameterTypes(queryEnvironment);
boolean result = paramTypes1.size() == paramTypes2.size();
final Iterator<IType> it1 = paramTypes1.iterator();
final Iterator<IType> it2 = paramTypes2.iterator();
while (result && it1.hasNext()) {
IType paramType1 = it1.next();
IType paramType2 = it2.next();
if (!paramType2.equals(paramType1)) {
result = false;
}
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#isLowerOrEqualParameterTypes(org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment,
* org.eclipse.acceleo.query.runtime.IService)
*/
public boolean isLowerOrEqualParameterTypes(IReadOnlyQueryEnvironment queryEnvironment,
IService<?> service) {
final List<IType> paramTypes1 = getParameterTypes(queryEnvironment);
final List<IType> paramTypes2 = service.getParameterTypes(queryEnvironment);
boolean result = paramTypes1.size() == paramTypes2.size();
final Iterator<IType> it1 = paramTypes1.iterator();
final Iterator<IType> it2 = paramTypes2.iterator();
while (result && it1.hasNext()) {
IType paramType1 = it1.next();
IType paramType2 = it2.next();
if (!paramType2.isAssignableFrom(paramType1)) {
result = false;
}
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#matches(org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment,
* org.eclipse.acceleo.query.validation.type.IType[])
*/
public boolean matches(IReadOnlyQueryEnvironment queryEnvironment, IType[] argumentTypes) {
assert getNumberOfParameters() == argumentTypes.length;
boolean result = true;
final List<IType> parameterTypes = getParameterTypes(queryEnvironment);
for (int i = 0; i < parameterTypes.size() && result; i++) {
if (argumentTypes[i].getType() != null && !parameterTypes.get(i).isAssignableFrom(
argumentTypes[i])) {
result = false;
}
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#validateAllType(org.eclipse.acceleo.query.runtime.impl.ValidationServices,
* org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment, java.util.Map)
*/
@Override
public Set<IType> validateAllType(ValidationServices services, IReadOnlyQueryEnvironment queryEnvironment,
Map<List<IType>, Set<IType>> allTypes) {
final Set<IType> result = new LinkedHashSet<IType>();
for (Entry<List<IType>, Set<IType>> entry : allTypes.entrySet()) {
// FIXME check for "empty" and put a message instead.
result.addAll(entry.getValue());
}
return result;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#invoke(java.lang.Object[])
*/
@Override
public Object invoke(Object... arguments) throws AcceleoQueryEvaluationException {
final Object result;
try {
result = internalInvoke(arguments);
// CHECKSTYLE:OFF
} catch (Exception e) {
// CHECKSTYLE:ON
final Throwable cause;
final String message;
if (e.getCause() != null) {
cause = e.getCause();
} else {
cause = e;
}
message = cause.getMessage();
throw new AcceleoQueryEvaluationException(getShortSignature() + " with arguments " + Arrays
.deepToString(arguments) + " failed:\n\t" + message, cause);
}
return result;
}
/**
* Does the internal invocation.
*
* @param arguments
* arguments
* @return the result of the invocation
* @throws Exception
* when the invocation goes wrong
*/
protected abstract Object internalInvoke(Object[] arguments) throws Exception;
/**
* Build up the specified service's signature for reporting.
*
* @param argumentTypes
* the service's call argument types
* @return the specified service's signature
*/
protected String serviceShortSignature(Object[] argumentTypes) {
StringBuilder builder = new StringBuilder();
builder.append(getName()).append('(');
boolean first = true;
for (Object argType : argumentTypes) {
if (!first) {
builder.append(',');
} else {
first = false;
}
if (argType instanceof Class<?>) {
builder.append(((Class<?>)argType).getCanonicalName());
} else if (argType instanceof EClass) {
builder.append("EClass=" + ((EClass)argType).getName());
} else if (argType == null) {
builder.append("Object=null");
} else {
// should not happen
builder.append("Object=" + argType.toString());
}
}
return builder.append(')').toString();
}
/**
* {@inheritDoc}
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getLongSignature();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.acceleo.query.runtime.IService#getProposals(org.eclipse.acceleo.query.runtime.IReadOnlyQueryEnvironment,
* java.util.Set)
*/
@Override
public List<ICompletionProposal> getProposals(IReadOnlyQueryEnvironment queryEnvironment,
Set<IType> receiverTypes) {
return Collections.emptyList();
}
@Override
public Visibility getVisibility() {
return Visibility.PUBLIC;
}
}