/* * Copyright 2012 PRODYNA AG * * Licensed under the Eclipse Public License (EPL), Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php or * http://www.nabucco.org/License.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.nabucco.framework.generator.compiler.transformation.common.annotation; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.nabucco.framework.generator.parser.syntaxtree.AnnotationDeclaration; import org.nabucco.framework.generator.parser.syntaxtree.Node; import org.nabucco.framework.generator.parser.syntaxtree.NodeToken; import org.nabucco.framework.mda.logger.MdaLogger; import org.nabucco.framework.mda.logger.MdaLoggingFactory; /** * NabuccoAnnotationMapper * * @author Nicolas Moser, PRODYNA AG */ public class NabuccoAnnotationMapper { /** The logger */ private static MdaLogger logger = MdaLoggingFactory.getInstance().getLogger(NabuccoAnnotationMapper.class); /** Singleton instance. */ private static NabuccoAnnotationMapper instance = new NabuccoAnnotationMapper(); /** Private constructor. */ private NabuccoAnnotationMapper() { } /** * Singleton access. * * @return the NabuccoAnnotationMapper instance. */ public static NabuccoAnnotationMapper getInstance() { return instance; } /** * Mapps the annotation declaration to a list of {@link NabuccoAnnotation}. * * @param annotationDeclaration * the annotation declaration * * @param types * optional list of {@link NabuccoAnnotationGroupType} to filter by * * @return the list of annotations, probably filtered by the types */ public List<NabuccoAnnotation> mapToAnnotationList(AnnotationDeclaration annotationDeclaration, NabuccoAnnotationGroupType... types) { if (annotationDeclaration == null) { throw new IllegalArgumentException("Annotation Declaration is not valid."); } List<NabuccoAnnotation> annotationList = new ArrayList<NabuccoAnnotation>(); for (Node node : annotationDeclaration.nodeListOptional.nodes) { if (node instanceof NodeToken) { String annotationName = ((NodeToken) node).tokenImage; NabuccoAnnotation annotation = this.mapStringToAnnotation(annotationName); if (annotation == null) { logger.error("Cannot resolve annotation [", annotationName, "]."); } if (annotation != null) { if (types.length == 0) { annotationList.add(annotation); } else { for (NabuccoAnnotationGroupType type : types) { if (annotation.getGroupType() == type) { annotationList.add(annotation); break; } } } } } } return annotationList; } /** * Mapps the first annotation declaration of the given type to a {@link NabuccoAnnotation}. * * @param annotationDeclaration * the annotation declaration * @param type * the annotation type * * @return the fist annotation, filtered by the constant name, or null if none exists */ public NabuccoAnnotation mapToAnnotation(AnnotationDeclaration annotationDeclaration, NabuccoAnnotationType type) { for (Node node : annotationDeclaration.nodeListOptional.nodes) { String annotationName = ((NodeToken) node).tokenImage; if (node instanceof NodeToken && annotationName.startsWith(type.getName())) { NabuccoAnnotation annotation = this.mapStringToAnnotation(annotationName); if (annotation == null) { logger.error("Cannot resolve annotation [", annotationName, "]."); } return annotation; } } return null; } /** * Converts annotation declarations to a hashmap with type as a key * * @param annotationDeclaration * @return */ public Map<NabuccoAnnotationType, NabuccoAnnotation> convertAnnotationsToMap( AnnotationDeclaration annotationDeclaration) { Map<NabuccoAnnotationType, NabuccoAnnotation> retVal = new HashMap<NabuccoAnnotationType, NabuccoAnnotation>(); for (Node node : annotationDeclaration.nodeListOptional.nodes) { String annotationName = ((NodeToken) node).tokenImage; if (node instanceof NodeToken) { NabuccoAnnotation annotation = this.mapStringToAnnotation(annotationName); if (annotation == null) { logger.error("Cannot resolve annotation [", annotationName, "]."); } else { retVal.put(annotation.getType(), annotation); } } } return retVal; } /** * Mapps all annotation declarations of a given type to a list of {@link NabuccoAnnotation}. * * @param annotationDeclaration * the annotation declaration * @param type * the annotation type * * @return the list of annotations, filtered by the constant name, or null */ public List<NabuccoAnnotation> mapToAnnotationList(AnnotationDeclaration annotationDeclaration, NabuccoAnnotationType type) { List<NabuccoAnnotation> annotationList = new ArrayList<NabuccoAnnotation>(); for (Node node : annotationDeclaration.nodeListOptional.nodes) { String annotationName = ((NodeToken) node).tokenImage; if (node instanceof NodeToken && annotationName.startsWith(type.getName())) { NabuccoAnnotation annotation = this.mapStringToAnnotation(annotationName); if (annotation == null) { logger.error("Cannot resolve annotation [", annotationName, "]."); } annotationList.add(annotation); } } return annotationList; } /** * Mapps the list of annotation declarations to a {@link NabuccoAnnotation}. * * @param annotationDeclarationList * the list of annotation declaration * * @param constant * {@link NabuccoAnnotationConstants} to filter by * * @return the annotation, filtered by the constant name */ public NabuccoAnnotation mapToAnnotation(List<NabuccoAnnotation> annotationDeclarationList, NabuccoAnnotationType type) { for (NabuccoAnnotation nabuccoAnnotation : annotationDeclarationList) { if (nabuccoAnnotation.getType() == type) { return nabuccoAnnotation; } } return null; } /** * Checks if a given annotation is present in a given annotation declaration. * * @param annotationDeclaration * a annotation declaration * @param types * a list of types to filter for * * @return <code>true</code> only if the annotation is present, else <code>false</code> */ public boolean hasAnnotation(AnnotationDeclaration annotationDeclaration, NabuccoAnnotationType... types) { for (NabuccoAnnotationType type : types) { if (mapToAnnotation(annotationDeclaration, type) != null) { return true; } } return false; } /** * Checks whether a string representation is a valid annotation. * * @param annotationName * name of the annotation * * @return <b>true</b> if the name is a defined annotation, <b>false</b> if not */ public boolean isAnnotation(String annotationName) { return this.mapStringToAnnotation(annotationName) != null; } /** * Mapps the annotation string to a {@link NabuccoAnnotation} instance. * * @param annotationString * the annotation string * * @return the annotation instance containing key, value and type of the annotation */ private NabuccoAnnotation mapStringToAnnotation(String annotationString) { for (NabuccoAnnotationType type : NabuccoAnnotationType.values()) { String annotation = type.getName(); if (isAnnotation(annotationString, annotation)) { return new NabuccoAnnotation(type, trim(annotationString, annotation)); } } return null; } /** * Check whether the given string string is of the given annotation type. * * @param current * the string to check * @param annotation * the annotation key * * @return <b>true</b> if it is the annotation, <b>false</b> if not */ private boolean isAnnotation(String current, String annotation) { if (!(current.startsWith(annotation))) { return false; } if (current.length() == annotation.length()) { return true; } if (Character.isWhitespace(current.charAt(annotation.length()))) { return true; } return false; } /** * Removes the leading annotation name, leading and trailing whitespace or tabs and enclosing * quotes. * * @param annotation * the annotation string to trim * @param key * the annotation name to remove * * @return the trimmed value of the annotation */ private String trim(String annotation, String key) { return annotation.replaceFirst(key, "").replace("\t", "").trim().replace("\"", ""); } }