| /******************************************************************************* |
| * Copyright (c) 2013 BSI Business Systems Integration AG. |
| * 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: |
| * BSI Business Systems Integration AG - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.scout.sdk.internal.workspace.dto; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Deque; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jdt.core.IAnnotation; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IMemberValuePair; |
| import org.eclipse.jdt.core.IMethod; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.scout.commons.CollectionUtility; |
| import org.eclipse.scout.commons.CompareUtility; |
| import org.eclipse.scout.commons.StringUtility; |
| import org.eclipse.scout.sdk.extensions.runtime.classes.IRuntimeClasses; |
| import org.eclipse.scout.sdk.internal.ScoutSdk; |
| import org.eclipse.scout.sdk.internal.workspace.dto.formdata.CompositeFormDataTypeSourceBuilder; |
| import org.eclipse.scout.sdk.internal.workspace.dto.formdata.TableFieldBeanFormDataSourceBuilder; |
| import org.eclipse.scout.sdk.internal.workspace.dto.formdata.TableFieldFormDataSourceBuilder; |
| import org.eclipse.scout.sdk.internal.workspace.dto.pagedata.TableBeanDataSourceBuilder; |
| import org.eclipse.scout.sdk.internal.workspace.dto.pagedata.TableRowDataTypeSourceBuilder; |
| import org.eclipse.scout.sdk.sourcebuilder.annotation.AnnotationSourceBuilder; |
| import org.eclipse.scout.sdk.sourcebuilder.annotation.AnnotationSourceBuilderFactory; |
| import org.eclipse.scout.sdk.sourcebuilder.comment.CommentSourceBuilderFactory; |
| import org.eclipse.scout.sdk.sourcebuilder.method.IMethodSourceBuilder; |
| import org.eclipse.scout.sdk.sourcebuilder.type.ITypeSourceBuilder; |
| import org.eclipse.scout.sdk.util.ScoutUtility; |
| import org.eclipse.scout.sdk.util.jdt.JdtUtility; |
| import org.eclipse.scout.sdk.util.method.MethodReturnExpression; |
| import org.eclipse.scout.sdk.util.signature.IImportValidator; |
| import org.eclipse.scout.sdk.util.signature.ITypeParameterMapping; |
| import org.eclipse.scout.sdk.util.signature.SignatureCache; |
| import org.eclipse.scout.sdk.util.signature.SignatureUtility; |
| import org.eclipse.scout.sdk.util.type.TypeFilters; |
| import org.eclipse.scout.sdk.util.type.TypeUtility; |
| import org.eclipse.scout.sdk.util.typecache.ITypeHierarchy; |
| import org.eclipse.scout.sdk.workspace.dto.formdata.FormDataAnnotation; |
| import org.eclipse.scout.sdk.workspace.dto.formdata.FormDataDtoUpdateOperation; |
| import org.eclipse.scout.sdk.workspace.dto.pagedata.DataAnnotation; |
| import org.eclipse.scout.sdk.workspace.dto.pagedata.PageDataDtoUpdateOperation; |
| import org.eclipse.scout.sdk.workspace.type.ScoutTypeUtility; |
| import org.eclipse.scout.sdk.workspace.type.validationrule.ValidationRuleMethod; |
| |
| /** |
| * <h3>{@link DtoUtility}</h3> |
| * |
| * @author Andreas Hoegger |
| * @since 3.10.0 27.08.2013 |
| */ |
| public final class DtoUtility { |
| |
| private static final Pattern VALIDATION_RULE_PATTERN = Pattern.compile("[@]ValidationRule\\s*[(]\\s*([^)]*value\\s*=)?\\s*([^,)]+)([,][^)]*)?[)]", Pattern.DOTALL); |
| static final Pattern ENDING_SEMICOLON_PATTERN = Pattern.compile("\\;$"); |
| private static final String GENERATED_MSG = "This class is auto generated by the Scout SDK. No manual modifications recommended."; |
| private static final String GENERATED_JAVADOC = "<b>NOTE:</b><br>" + GENERATED_MSG + "\n\n@generated"; |
| |
| private DtoUtility() { |
| } |
| |
| private static AnnotationSourceBuilder getExtendsAnnotationSourceBuilder(IJavaElement element, ITypeHierarchy modelLocalHierarchy) throws CoreException { |
| if (element instanceof IType) { |
| IType extendedType = ScoutTypeUtility.getExtendedType((IType) element, modelLocalHierarchy); |
| if (extendedType != null) { |
| IType primaryType = TypeUtility.getPrimaryType(extendedType); |
| ITypeHierarchy primaryTypeSuperHierarchy = TypeUtility.getSupertypeHierarchy(primaryType); |
| if (primaryTypeSuperHierarchy != null) { |
| IType extendedDto = null; |
| if (primaryTypeSuperHierarchy.contains(TypeUtility.getType(IRuntimeClasses.IForm)) || primaryTypeSuperHierarchy.contains(TypeUtility.getType(IRuntimeClasses.IFormField))) { |
| ITypeHierarchy extendedTypeSuperHierarchy = TypeUtility.getSupertypeHierarchy(extendedType); |
| if (extendedTypeSuperHierarchy.contains(TypeUtility.getType(IRuntimeClasses.ITable)) && extendedType.getDeclaringType() != null) { |
| IType tableFieldDto = getFormDataType(extendedType.getDeclaringType(), extendedTypeSuperHierarchy); |
| extendedDto = getRowDataFor(tableFieldDto); |
| } |
| else { |
| extendedDto = ScoutTypeUtility.findDtoForForm(primaryType); |
| } |
| } |
| else if (primaryTypeSuperHierarchy.contains(TypeUtility.getType(IRuntimeClasses.IExtension))) { |
| extendedDto = ScoutTypeUtility.findDtoForPage(primaryType); |
| } |
| else if (primaryTypeSuperHierarchy.contains(TypeUtility.getType(IRuntimeClasses.IPageWithTable))) { |
| IType pageDto = ScoutTypeUtility.findDtoForPage(primaryType); |
| Set<IType> innerTypes = TypeUtility.getInnerTypes(pageDto, TypeFilters.getSubtypeFilter(IRuntimeClasses.AbstractTableRowData)); |
| extendedDto = CollectionUtility.firstElement(innerTypes); |
| } |
| |
| if (extendedDto != null) { |
| final IType dto = extendedDto; |
| AnnotationSourceBuilder asb = new AnnotationSourceBuilder(SignatureCache.createTypeSignature(IRuntimeClasses.Extends)) { |
| @Override |
| public void createSource(StringBuilder source, String lineDelimiter, IJavaProject ownerProject, IImportValidator validator) throws CoreException { |
| String typeName = validator.getTypeName(SignatureCache.createTypeSignature(dto.getFullyQualifiedName())); |
| addParameter(typeName + ".class"); |
| super.createSource(source, lineDelimiter, ownerProject, validator); |
| } |
| }; |
| return asb; |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| private static IType getRowDataFor(IType tableDto) { |
| if (tableDto == null) { |
| return null; |
| } |
| Set<IType> innerTypes = TypeUtility.getInnerTypes(tableDto, TypeFilters.getSubtypeFilter(IRuntimeClasses.AbstractTableRowData)); |
| return CollectionUtility.firstElement(innerTypes); |
| } |
| |
| public static void addFormDataAdditionalInterfaces(FormDataAnnotation formDataAnnotation, ITypeSourceBuilder sourceBuilder, IJavaProject formDataJavaProject) { |
| Set<String> interfaceSignatures = formDataAnnotation.getInterfaceSignatures(); |
| if (interfaceSignatures.isEmpty()) { |
| return; |
| } |
| |
| Set<IType> allSuperInterfaces = new HashSet<IType>(); |
| for (String ifcSig : interfaceSignatures) { |
| IType ifcType = TypeUtility.getTypeBySignature(ifcSig); |
| |
| if (TypeUtility.isOnClasspath(ifcType, formDataJavaProject)) { |
| sourceBuilder.addInterfaceSignature(ifcSig); |
| allSuperInterfaces.addAll(TypeUtility.getSupertypeHierarchy(ifcType).getAllInterfaces()); |
| } |
| } |
| Set<String> allSuperInterfaceMethods = new HashSet<String>(); |
| try { |
| for (IType t : allSuperInterfaces) { |
| for (IMethod m : t.getMethods()) { |
| allSuperInterfaceMethods.add(SignatureUtility.getMethodIdentifier(m)); |
| } |
| } |
| } |
| catch (CoreException e) { |
| ScoutSdk.logError("Unable to read existing methods from super interfaces of formdata for '" + formDataAnnotation.getAnnotationOwner().getElementName() + "'. The resulting formdata may miss some @Override annotations.", e); |
| } |
| for (IMethodSourceBuilder msb : sourceBuilder.getMethodSourceBuilders()) { |
| if (allSuperInterfaceMethods.contains(msb.getMethodIdentifier())) { |
| msb.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createOverrideAnnotationSourceBuilder()); |
| } |
| } |
| } |
| |
| public static ITypeSourceBuilder createTableRowDataTypeSourceBuilder(IType modelType, DataAnnotation dataAnnotation, IProgressMonitor monitor) throws CoreException { |
| String dataTypeName = Signature.getSignatureSimpleName(dataAnnotation.getDataTypeSignature()); |
| ITypeHierarchy modelLocalHierarchy = TypeUtility.getLocalTypeHierarchy(modelType); |
| |
| ITypeSourceBuilder rowDataSourceBuilder = new TableRowDataTypeSourceBuilder(dataTypeName, modelType, modelType, modelLocalHierarchy, monitor); |
| |
| // primary class comment |
| rowDataSourceBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createCustomCommentBuilder(GENERATED_JAVADOC)); |
| |
| // @Extends annotation |
| addDtoExtendsAnnotation(rowDataSourceBuilder, dataAnnotation.getAnnotationHolder(), modelLocalHierarchy); |
| |
| //@Generated annotation |
| rowDataSourceBuilder.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createGeneratedAnnotation(PageDataDtoUpdateOperation.class.getName(), GENERATED_MSG)); |
| |
| return rowDataSourceBuilder; |
| } |
| |
| public static ITypeSourceBuilder createPageDataSourceBuilder(IType modelType, DataAnnotation pageDataAnnotation, ICompilationUnit pageDataIcu, IProgressMonitor monitor) { |
| String pageDataSignature = pageDataAnnotation.getDataTypeSignature(); |
| ITypeHierarchy modelLocalHierarchy = TypeUtility.getLocalTypeHierarchy(modelType); |
| |
| ITypeSourceBuilder pageDataSourceBuilder = new TableBeanDataSourceBuilder(modelType, modelLocalHierarchy, Signature.getSignatureSimpleName(pageDataSignature), pageDataAnnotation, pageDataIcu, monitor); |
| |
| // primary class comment |
| pageDataSourceBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createCustomCommentBuilder(GENERATED_JAVADOC)); |
| |
| //@Generated annotation |
| pageDataSourceBuilder.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createGeneratedAnnotation(PageDataDtoUpdateOperation.class.getName(), GENERATED_MSG)); |
| return pageDataSourceBuilder; |
| } |
| |
| public static ITypeSourceBuilder createFormDataSourceBuilder(IType modelType, FormDataAnnotation formDataAnnotation, ICompilationUnit formDataIcu, IProgressMonitor monitor) { |
| String superTypeSignature = formDataAnnotation.getSuperTypeSignature(); |
| if (StringUtility.hasText(superTypeSignature)) { |
| IType superType = TypeUtility.getTypeBySignature(superTypeSignature); |
| ITypeHierarchy superTypeHierarchy = TypeUtility.getSupertypeHierarchy(superType); |
| ITypeHierarchy modelLocalHierarchy = TypeUtility.getLocalTypeHierarchy(modelType); |
| String formDataTypeName = Signature.getSignatureSimpleName(formDataAnnotation.getFormDataTypeSignature()); |
| |
| ITypeSourceBuilder formDataSourceBuilder = null; |
| if (superTypeHierarchy != null && superTypeHierarchy.contains(TypeUtility.getType(IRuntimeClasses.AbstractTableFieldData))) { |
| // fill table legacy |
| formDataSourceBuilder = new TableFieldFormDataSourceBuilder(modelType, modelLocalHierarchy, formDataTypeName, formDataAnnotation, formDataIcu, monitor); |
| } |
| else if (superTypeHierarchy != null && superTypeHierarchy.contains(TypeUtility.getType(IRuntimeClasses.AbstractTableFieldBeanData))) { |
| // fill table bean |
| formDataSourceBuilder = new TableFieldBeanFormDataSourceBuilder(modelType, modelLocalHierarchy, formDataTypeName, formDataAnnotation, formDataIcu, monitor); |
| } |
| else { |
| formDataSourceBuilder = new CompositeFormDataTypeSourceBuilder(modelType, modelLocalHierarchy, formDataTypeName, formDataAnnotation, formDataIcu, monitor); |
| } |
| |
| // primary class comment |
| formDataSourceBuilder.setCommentSourceBuilder(CommentSourceBuilderFactory.createCustomCommentBuilder(GENERATED_JAVADOC)); |
| |
| // @Extends annotation |
| addDtoExtendsAnnotation(formDataSourceBuilder, formDataAnnotation.getAnnotationOwner(), modelLocalHierarchy); |
| |
| // @Generated annotation |
| formDataSourceBuilder.addAnnotationSourceBuilder(AnnotationSourceBuilderFactory.createGeneratedAnnotation(FormDataDtoUpdateOperation.class.getName(), GENERATED_MSG)); |
| |
| // add interfaces and @Override annotation for all methods that exist in the given interfaces |
| addFormDataAdditionalInterfaces(formDataAnnotation, formDataSourceBuilder, formDataIcu.getJavaProject()); |
| |
| return formDataSourceBuilder; |
| } |
| return null; |
| } |
| |
| private static void addDtoExtendsAnnotation(ITypeSourceBuilder target, IJavaElement extendsAnnotationHolder, ITypeHierarchy modelLocalHierarchy) { |
| if (TypeUtility.existsType(IRuntimeClasses.Extends)) { |
| try { |
| AnnotationSourceBuilder extendsAnnotation = getExtendsAnnotationSourceBuilder(extendsAnnotationHolder, modelLocalHierarchy); |
| if (extendsAnnotation != null) { |
| target.addAnnotationSourceBuilder(extendsAnnotation); |
| } |
| } |
| catch (CoreException e) { |
| ScoutSdk.logError("Unable to calculate @Extends annotation value of owner '" + extendsAnnotationHolder.getElementName() + "'.", e); |
| } |
| } |
| } |
| |
| public static IType findTable(IType tableOwner, ITypeHierarchy hierarchy) { |
| if (TypeUtility.exists(tableOwner)) { |
| if (hierarchy == null) { |
| hierarchy = TypeUtility.getLocalTypeHierarchy(tableOwner); |
| } |
| Set<IType> tables = TypeUtility.getInnerTypes(tableOwner, TypeFilters.getSubtypeFilter(TypeUtility.getType(IRuntimeClasses.ITable), hierarchy), null); |
| if (tables.size() > 0) { |
| if (tables.size() > 1) { |
| ScoutSdk.logWarning("table field '" + tableOwner.getFullyQualifiedName() + "' contains more than one table! Using first one for DTO creation."); |
| } |
| return CollectionUtility.firstElement(tables); |
| } |
| else { |
| IType superclass = hierarchy.getSuperclass(tableOwner); |
| return findTable(superclass, null); |
| } |
| } |
| return null; |
| } |
| |
| private static String computeDtoGenericType(IType contextType, IType annotationOwnerType, int genericOrdinal, ITypeHierarchy formFieldHierarchy) throws CoreException { |
| if (!TypeUtility.exists(contextType) || contextType.getFullyQualifiedName().equals(Object.class.getName()) || !TypeUtility.exists(annotationOwnerType)) { |
| return null; |
| } |
| |
| Map<String, ITypeParameterMapping> collector = SignatureUtility.resolveTypeParameters(contextType, formFieldHierarchy); |
| |
| boolean annotOwnerPassed = false; |
| for (Entry<String, ITypeParameterMapping> entry : collector.entrySet()) { |
| if (!annotOwnerPassed && CompareUtility.equals(annotationOwnerType.getFullyQualifiedName(), entry.getKey())) { |
| annotOwnerPassed = true; |
| } |
| |
| if (annotOwnerPassed) { |
| ITypeParameterMapping genericMapping = entry.getValue(); |
| if (genericMapping.getParameterCount() > genericOrdinal) { |
| return CollectionUtility.firstElement(genericMapping.getTypeParameterBounds(genericOrdinal)); |
| } |
| } |
| } |
| return null; |
| } |
| |
| public static String computeSuperTypeSignatureForFormData(IType formField, FormDataAnnotation formDataAnnotation, ITypeHierarchy localHierarchy) { |
| String superTypeSignature = formDataAnnotation.getSuperTypeSignature(); |
| if (formDataAnnotation.getGenericOrdinal() >= 0) { |
| IType genericOrdinalDefinitionType = formDataAnnotation.getGenericOrdinalDefinitionType(); |
| if (TypeUtility.exists(genericOrdinalDefinitionType)) { |
| IType superType = TypeUtility.getTypeBySignature(superTypeSignature); |
| if (TypeUtility.isGenericType(superType)) { |
| try { |
| String genericTypeSig = computeDtoGenericType(formField, genericOrdinalDefinitionType, formDataAnnotation.getGenericOrdinal(), localHierarchy); |
| if (genericTypeSig != null) { |
| superTypeSignature = ENDING_SEMICOLON_PATTERN.matcher(superTypeSignature).replaceAll(Signature.C_GENERIC_START + genericTypeSig + Signature.C_GENERIC_END + Signature.C_SEMICOLON); |
| } |
| } |
| catch (CoreException e) { |
| ScoutSdk.logError("could not find generic type for form data of type '" + formField.getFullyQualifiedName() + "'.", e); |
| } |
| } |
| } |
| } |
| return superTypeSignature; |
| } |
| |
| public static List<ValidationRuleMethod> getValidationRuleMethods(IType declaringType, ITypeHierarchy superTypeHierarchy, IProgressMonitor monitor) throws JavaModelException { |
| IType validationRuleType = TypeUtility.getType(IRuntimeClasses.ValidationRule); |
| TreeMap<String, ValidationRuleMethod> ruleMap = new TreeMap<String, ValidationRuleMethod>(); |
| if (superTypeHierarchy == null) { |
| superTypeHierarchy = TypeUtility.getSupertypeHierarchy(declaringType); |
| if (superTypeHierarchy == null) { |
| ScoutSdk.logWarning("could not build super type hierarchy for '" + declaringType.getFullyQualifiedName() + "'."); |
| return Collections.emptyList(); |
| } |
| } |
| |
| Deque<IType> superClassStack = superTypeHierarchy.getSuperClassStack(declaringType); |
| IType[] targetTypes = superClassStack.toArray(new IType[superClassStack.size()]); |
| IMethod[][] targetMethods = new IMethod[targetTypes.length][]; |
| for (int i = 0; i < targetTypes.length; i++) { |
| targetMethods[i] = targetTypes[i].getMethods(); |
| } |
| if (monitor.isCanceled()) { |
| return null; |
| } |
| |
| HashSet<String> visitedMethodNames = new HashSet<String>(); |
| for (int i = 0; i < targetTypes.length; i++) { |
| for (IMethod annotatedMethod : targetMethods[i]) { |
| if (monitor.isCanceled()) { |
| return null; |
| } |
| |
| if (!TypeUtility.exists(annotatedMethod)) { |
| continue; |
| } |
| if (visitedMethodNames.contains(annotatedMethod.getElementName())) { |
| continue; |
| } |
| IAnnotation validationRuleAnnotation = JdtUtility.getAnnotation(annotatedMethod, IRuntimeClasses.ValidationRule); |
| if (!TypeUtility.exists(validationRuleAnnotation)) { |
| continue; |
| } |
| |
| //extract rule name and generated code order |
| visitedMethodNames.add(annotatedMethod.getElementName()); |
| IMemberValuePair[] pairs = validationRuleAnnotation.getMemberValuePairs(); |
| if (pairs == null) { |
| continue; |
| } |
| String ruleString = null; |
| Boolean ruleSkip = false; |
| MethodReturnExpression methodReturnExpression = null; |
| for (IMemberValuePair pair : pairs) { |
| if ("value".equals(pair.getMemberName())) { |
| if (pair.getValue() instanceof String) { |
| ruleString = (String) pair.getValue(); |
| } |
| } |
| else if ("generatedSourceCode".equals(pair.getMemberName())) { |
| if (pair.getValue() instanceof String) { |
| methodReturnExpression = new MethodReturnExpression(); |
| methodReturnExpression.setReturnClause((String) pair.getValue()); |
| } |
| } |
| else if ("skip".equals(pair.getMemberName())) { |
| if (pair.getValue() instanceof Boolean) { |
| ruleSkip = (Boolean) pair.getValue(); |
| } |
| } |
| } |
| if (ruleString == null) { |
| continue; |
| } |
| //find out the annotated source code field name (constant declaration) |
| //this is either ValidationRule(value=text ) or simply ValidationRule(text) |
| IField ruleField = null; |
| Matcher annotationMatcher = VALIDATION_RULE_PATTERN.matcher("" + annotatedMethod.getSource()); |
| if (annotationMatcher.find()) { |
| String fieldSource = annotationMatcher.group(2).trim(); |
| int lastDot = fieldSource.lastIndexOf('.'); |
| //fast check if scout rule |
| if (fieldSource.startsWith("ValidationRule")) { |
| if (TypeUtility.exists(validationRuleType)) { |
| ruleField = validationRuleType.getField(fieldSource.substring(lastDot + 1)); |
| if (!TypeUtility.exists(ruleField)) { |
| ruleField = null; |
| } |
| } |
| } |
| else if (!fieldSource.startsWith("\"") && lastDot > 0) { |
| IType fieldBaseType = TypeUtility.getReferencedType(annotatedMethod.getDeclaringType(), fieldSource.substring(0, lastDot), false); |
| |
| if (fieldBaseType != null) { |
| ruleField = fieldBaseType.getField(fieldSource.substring(lastDot + 1)); |
| if (!TypeUtility.exists(ruleField)) { |
| ruleField = null; |
| } |
| } |
| } |
| } |
| if (ruleField != null) { |
| Object val = TypeUtility.getFieldConstant(ruleField); |
| if (val instanceof String) { |
| ruleString = (String) val; |
| } |
| } |
| String hashKey = ruleString; |
| if (ruleMap.containsKey(hashKey)) { |
| continue; |
| } |
| //found new rule annotation, now find most specific method in subclasses to generate source code |
| IMethod implementedMethod = null; |
| if (methodReturnExpression == null) { |
| for (int k = 0; k < i; k++) { |
| for (IMethod tst : targetMethods[k]) { |
| if (!TypeUtility.exists(tst)) { |
| continue; |
| } |
| if (tst.getElementName().equals(annotatedMethod.getElementName())) { |
| implementedMethod = tst; |
| break; |
| } |
| } |
| if (implementedMethod != null) { |
| break; |
| } |
| } |
| if (implementedMethod == null) { |
| implementedMethod = annotatedMethod; |
| } |
| //found most specific override of new rule |
| methodReturnExpression = ScoutUtility.getMethodReturnExpression(implementedMethod); |
| } |
| else { |
| implementedMethod = annotatedMethod; |
| } |
| //new rule is sufficiently parsed |
| ValidationRuleMethod vm = new ValidationRuleMethod(validationRuleAnnotation, ruleField, ruleString, methodReturnExpression, annotatedMethod, implementedMethod, superTypeHierarchy, ruleSkip); |
| ruleMap.put(hashKey, vm); |
| } |
| } |
| |
| ArrayList<ValidationRuleMethod> list = new ArrayList<ValidationRuleMethod>(ruleMap.size()); |
| for (ValidationRuleMethod v : ruleMap.values()) { |
| if (v != null) { |
| list.add(v); |
| } |
| } |
| return list; |
| } |
| |
| /** |
| * @return Returns the form field data for the given form field or <code>null</code> if it does not have one. |
| * @since 3.8.2 |
| */ |
| public static IType getFormDataType(IType formField, ITypeHierarchy hierarchy) throws JavaModelException { |
| IType primaryType = getFormFieldDataPrimaryTypeRec(formField, hierarchy); |
| if (!TypeUtility.exists(primaryType)) { |
| return null; |
| } |
| |
| // check if the primary type itself is the correct type |
| String formDataName = ScoutUtility.removeFieldSuffix(formField.getElementName()); |
| if (primaryType.getElementName().equals(formDataName)) { |
| return primaryType; |
| } |
| |
| // search field data within form data |
| IType formDataType = TypeUtility.findInnerType(primaryType, formDataName); |
| if (TypeUtility.exists(formDataType)) { |
| return formDataType; |
| } |
| return null; |
| } |
| |
| /** |
| * @return Returns the form field data for the given form field or <code>null</code> if it does not have one. The |
| * method walks recursively through the list of declaring classes until it has reached a primary type. |
| * @since 3.8.2 |
| */ |
| private static IType getFormFieldDataPrimaryTypeRec(IType recursiveDeclaringType, ITypeHierarchy hierarchy) throws JavaModelException { |
| if (!TypeUtility.exists(recursiveDeclaringType)) { |
| return null; |
| } |
| FormDataAnnotation formDataAnnotation = ScoutTypeUtility.findFormDataAnnotation(recursiveDeclaringType, hierarchy); |
| if (FormDataAnnotation.isIgnore(formDataAnnotation)) { |
| return null; |
| } |
| |
| IType declaringType = recursiveDeclaringType.getDeclaringType(); |
| if (declaringType == null) { |
| // primary type |
| if (FormDataAnnotation.isSdkCommandCreate(formDataAnnotation) || FormDataAnnotation.isSdkCommandUse(formDataAnnotation)) { |
| return TypeUtility.getTypeBySignature(formDataAnnotation.getFormDataTypeSignature()); |
| } |
| return null; |
| } |
| |
| return getFormFieldDataPrimaryTypeRec(declaringType, hierarchy); |
| } |
| } |