/******************************************************************************* * Copyright (c) 2012 BMW Car IT 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.jnario.spec.naming; import static com.google.common.collect.Iterables.addAll; import static com.google.common.collect.Iterables.filter; import static com.google.common.collect.Lists.newArrayList; import static java.lang.Math.max; import static org.eclipse.xtext.EcoreUtil2.getContainerOfType; import static org.eclipse.xtext.util.Strings.toFirstUpper; import static org.jnario.util.Nodes.textForFeature; import static org.jnario.util.Strings.convertToCamelCase; import static org.jnario.util.Strings.makeJunitConform; import static org.jnario.util.Strings.markAsPending; import java.util.List; import java.util.Stack; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtend.core.xtend.XtendClass; import org.eclipse.xtext.common.types.JvmParameterizedTypeReference; import org.eclipse.xtext.common.types.JvmTypeReference; import org.eclipse.xtext.common.types.TypesPackage; import org.eclipse.xtext.naming.QualifiedName; import org.jnario.ExampleTable; import org.jnario.jvmmodel.JnarioNameProvider; import org.jnario.spec.spec.After; import org.jnario.spec.spec.Before; import org.jnario.spec.spec.Example; import org.jnario.spec.spec.ExampleGroup; import org.jnario.spec.spec.SpecPackage; import org.jnario.spec.spec.TestFunction; import org.jnario.util.Strings; import com.google.inject.Inject; import com.google.inject.Singleton; /** * @author Sebastian Benz - Initial contribution and API */ @SuppressWarnings("restriction") @Singleton public class ExampleNameProvider extends JnarioNameProvider{ private static final String SPEC_POSTFIX = "Spec"; ExampleNameProvider() { } @Inject private OperationNameProvider operationNameProvider; protected String internalToMethodName(EObject eObject){ if(eObject == null){ return null; } if (eObject instanceof After) { return _toMethodName((After)eObject); } if (eObject instanceof Before) { return _toMethodName((Before)eObject); } if (eObject instanceof Example) { return _toMethodName((Example)eObject); } throw new UnsupportedOperationException("Cannot determine method name for " + eObject.eClass().getName()); } protected String internalDescribe(EObject eObject) { if(eObject == null){ return null; } if (eObject instanceof ExampleGroup) { return _describe((ExampleGroup) eObject); } if (eObject instanceof Example) { return _describe((Example) eObject); } throw new UnsupportedOperationException("Cannote describe " + eObject.eClass().getName()); } protected String internalToJavaClassName(EObject eObject) { if(eObject == null){ return null; } if (eObject instanceof ExampleGroup) { return _toJavaClassName((ExampleGroup) eObject); } if (eObject instanceof ExampleTable) { return _toJavaClassName((ExampleTable) eObject); } if (eObject instanceof XtendClass) { return ((XtendClass)eObject).getName(); } ExampleGroup exampleGroup = getContainerOfType(eObject, ExampleGroup.class); if(exampleGroup == null){ return null; } return _toJavaClassName(exampleGroup); } private String _describe(ExampleGroup exampleGroup) { StringBuilder result = new StringBuilder(); if(exampleGroup.getTargetType() != null){ result.append(getTargetTypeName(exampleGroup)); result.append(" "); } if(hasTargetOperation(exampleGroup)){ result.append(getOperationName(exampleGroup, true)); result.append(" "); } if(exampleGroup.getName() != null){ result.append(exampleGroup.getName()); } return makeJunitConform(result); } private QualifiedName getOperationName(ExampleGroup exampleGroup, boolean withParameters) { EObject operation = (EObject) exampleGroup.eGet(SpecPackage.Literals.EXAMPLE_GROUP__TARGET_OPERATION, false); if(!withParameters || operation.eIsProxy()){ String name = textForFeature(exampleGroup, SpecPackage.Literals.EXAMPLE_GROUP__TARGET_OPERATION); return QualifiedName.create(name); } return operationNameProvider.apply(exampleGroup.getTargetOperation()); } private String _describe(Example example){ StringBuilder sb = new StringBuilder(); if(example.getName() != null){ sb.append(example.getName()); } if(example.isPending()){ markAsPending(sb); } return makeJunitConform(sb).trim(); } private String _toJavaClassName(ExampleGroup exampleGroup){ StringBuilder result = internalGetName(exampleGroup); result.append(SPEC_POSTFIX); return result.toString(); } private String _toMethodName(Example example){ String name = ""; if(example.getName() != null){ name = example.getName(); } return Strings.toMethodName(name); } private String _toMethodName(Before before){ String name = "before"; return _toMethodName(before, name); } private String _toMethodName(After after){ String name = "after"; return _toMethodName(after, name); } private String _toMethodName(TestFunction target, String defaultName){ if(target.getName() != null){ return Strings.toMethodName(target.getName()); } if(target.isStatic()){ defaultName += "All"; } int count = countPreviousWithDefaultName(target); if(count > 1){ defaultName += count; } return defaultName; } protected String internalToFieldName(EObject eObject){ if (eObject instanceof ExampleTable) { ExampleTable exampleTable = (ExampleTable) eObject; String name = exampleTable.getName(); return name == null ? "examples" : name; } throw new UnsupportedOperationException("Cannot determin field name for " + eObject.eClass().getName()); } private String _toJavaClassName(ExampleTable exampleTable){ ExampleGroup parent = getContainerOfType(exampleTable, ExampleGroup.class); return toJavaClassName(parent) + toFirstUpper(toFieldName(exampleTable)); } private int countPreviousWithDefaultName(TestFunction target) { List<? extends TestFunction> members = allMembers(target, target.getClass()); int index = members.indexOf(target); int count = 1; for (int i = 0; i < index; i++) { TestFunction current = members.get(i); if (current.getClass() == target.getClass()) { if(current.getName() == null && current.isStatic() == target.isStatic()){ count++; } } } return count; } private <T extends TestFunction> List<T> allMembers(EObject context, Class<T> type) { XtendClass container = getContainerOfType(context, XtendClass.class); Stack<XtendClass> parents = new Stack<XtendClass>(); while(container != null){ parents.push(container); container = getContainerOfType(container.eContainer(), XtendClass.class); } List<T> functions = newArrayList(); while(!parents.isEmpty()){ addAll(functions, filter(parents.pop().getMembers(), type)); } return functions; } private StringBuilder internalGetName(ExampleGroup exampleGroup) { StringBuilder result = new StringBuilder(); if(exampleGroup.eContainer() != null){ ExampleGroup parent = getContainerOfType(exampleGroup.eContainer(), ExampleGroup.class); if(parent != null){ result.append(internalGetName(parent)); } } if(exampleGroup.getTargetType() != null){ result.append(getTargetTypeName(exampleGroup)); } if(hasTargetOperation(exampleGroup)){ String operationName = getOperationName(exampleGroup, false).toString(); result.append(toFirstUpper(operationName)); } if(exampleGroup.getName() != null){ result.append(toFirstUpper(exampleGroup.getName())); } result = convertToCamelCase(result); return result; } private String getTargetTypeName(ExampleGroup exampleGroup) { String targetName; if(isProxy(exampleGroup.getTargetType())){ targetName = resolveProxyTypeName(exampleGroup); }else{ targetName = exampleGroup.getTargetType().getSimpleName(); } return targetName; } private boolean hasTargetOperation(ExampleGroup exampleGroup) { return exampleGroup.eIsSet(SpecPackage.Literals.EXAMPLE_GROUP__TARGET_OPERATION); } private String resolveProxyTypeName(ExampleGroup exampleGroup) { String text = textForFeature(exampleGroup, SpecPackage.Literals.EXAMPLE_GROUP__TARGET_TYPE); int begin = max(text.lastIndexOf('.'), text.lastIndexOf('$')) + 1; int end = text.indexOf('<'); if(end == -1){ end = text.length(); } return text.substring(begin, end); } private boolean isProxy(JvmTypeReference jvmTypeReference) { if (jvmTypeReference instanceof JvmParameterizedTypeReference) { JvmParameterizedTypeReference parameterizedTypeReference = (JvmParameterizedTypeReference) jvmTypeReference; EObject value = (EObject) parameterizedTypeReference.eGet(TypesPackage.Literals.JVM_PARAMETERIZED_TYPE_REFERENCE__TYPE, false); return value.eIsProxy(); }else{ return true; } } }