org.eclipse.emf.teneo.annotations.parser.EAnnotationParserImporter.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.emf.teneo.annotations.parser.EAnnotationParserImporter.java

Source

/**
 * <copyright>
 *
 * Copyright (c) 2005, 2006, 2007, 2008 Springsite BV (The Netherlands) 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:
 *   Martin Taal
 * </copyright>
 *
 * $Id: EAnnotationParserImporter.java,v 1.8 2010/02/04 11:02:59 mtaal Exp $
 */

package org.eclipse.emf.teneo.annotations.parser;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.teneo.Constants;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEClass;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEDataType;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEModelElement;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEPackage;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedEStructuralFeature;
import org.eclipse.emf.teneo.annotations.pamodel.PAnnotatedModel;
import org.eclipse.emf.teneo.annotations.pannotation.PannotationPackage;
import org.eclipse.emf.teneo.extension.ExtensionPoint;

/**
 * Walks over the pamodel and the paepackages and translates eannotations to
 * pannotation types and sets the corresponding values in the pamodel.
 * 
 * @author <a href="mailto:mtaal at elver.org">Martin Taal</a>
 */
public class EAnnotationParserImporter implements EClassResolver, ExtensionPoint {
    /** Log it */
    private final static Log log = LogFactory.getLog(EAnnotationParserImporter.class);

    /** annotation parser */
    private AnnotationParser annotationParser = new AnnotationParser();

    /** The prefix to distinguish jpa annotations from hb or jpox annotations */
    private static final String JPA_PREFIX = "jpa:";

    private String[] extraAnnotationsSources = new String[] {};

    /** Parse an pamodel */
    public void process(PAnnotatedModel paModel) {
        for (PAnnotatedEPackage pap : paModel.getPaEPackages()) {
            log.debug("Processing package " + pap.getModelEPackage().getName());
            processAnnotatedModelElement(pap, pap.eClass().getEPackage());

            // and now the eclasses
            process(pap);
        }
    }

    /** Process package */
    protected void process(PAnnotatedEPackage pap) {
        for (PAnnotatedEClass pac : pap.getPaEClasses()) {
            processAnnotatedModelElement(pac, pac.getModelEClass().getEPackage());
            process(pac);
        }
        for (PAnnotatedEDataType pac : pap.getPaEDataTypes()) {
            processAnnotatedModelElement(pac, pac.getModelEDataType().getEPackage());
        }
    }

    /** Process the efeatures */
    protected void process(PAnnotatedEClass pac) {
        log.debug("Processing eclass " + pac.getModelEClass().getName());
        for (PAnnotatedEStructuralFeature paf : pac.getPaEStructuralFeatures()) {
            processAnnotatedModelElement(paf, paf.getModelEStructuralFeature().eClass().getEPackage());
        }
    }

    /** Process a type with its eannotations */
    @SuppressWarnings("unchecked")
    protected void processAnnotatedModelElement(PAnnotatedEModelElement pee, EPackage epack) {
        log.debug("Processing " + pee.getModelElement().getName());
        final ArrayList<NamedParserNode> parsedNodes = new ArrayList<NamedParserNode>();
        for (EAnnotation annotation : pee.getModelElement().getEAnnotations()) {
            parsedNodes.addAll(process(annotation, pee.getModelElement()));
        }

        // now also do the annotations on the edatatype (if any)
        /*
         * if (pee.getAnnotatedElement() instanceof EAttribute) { final
         * EAttribute eattr = (EAttribute)pee.getAnnotatedElement(); final
         * EDataType edt = (EDataType)eattr.getEType(); for (Iterator it =
         * edt.getEAnnotations().iterator(); it.hasNext();) {
         * parsedNodes.addAll(process((EAnnotation)it.next(),
         * pee.getAnnotatedElement())); } }
         */

        // now the parsed nodes should be translated into features of the
        // enamedelement
        // this is done multiplelevel
        log.debug("Number of parsed typename annotations " + parsedNodes.size());
        for (NamedParserNode namedParserNode : parsedNodes) {
            final ComplexNode cn = (ComplexNode) namedParserNode;
            if (cn.isList()) {
                // find the efeature
                final EStructuralFeature ef = getEStructuralFeature(pee.eClass(), cn.getName());
                pee.eSet(ef, cn.convert(this));
            } else {
                EObject eobj = (EObject) cn.convert(this);
                boolean found = false;
                // first find exact type
                for (EReference eref : pee.eClass().getEAllReferences()) {
                    if (eref.getEReferenceType() == eobj.eClass()) {
                        log.debug("Found EReference " + eref.getName() + " for " + eobj.eClass().getName());
                        if (eref.isMany()) {
                            ((List<EObject>) pee.eGet(eref)).add(eobj);
                        } else {
                            pee.eSet(eref, eobj);
                        }
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    for (EReference eref : pee.eClass().getEAllReferences()) {
                        if (eref.getEReferenceType().isInstance(eobj)) {
                            log.debug("Found EReference " + eref.getName() + " for " + eobj.eClass().getName());
                            if (eref.isMany()) {
                                ((List<EObject>) pee.eGet(eref)).add(eobj);
                            } else {
                                pee.eSet(eref, eobj);
                            }
                            found = true;
                            break;
                        }
                    }
                }
                if (!found) {
                    throw new AnnotationParserException("The eclass: " + pee.eClass().getName()
                            + " does not have an efeature for " + eobj.eClass().getName());
                }
            }
        }

        // now for each eobject find which eref stores it!
        // log.debug("Find efeature for each created eobject");
        // final ArrayList objects = new ArrayList();
        // for (Iterator it = objects.iterator(); it.hasNext();) {
        // EObject eobj = (EObject)it.next();
        // log.debug("EClass " + eobj.eClass().getName());
        // }
    }

    /** Processes EAnnotations */
    private ArrayList<NamedParserNode> process(EAnnotation ea, ENamedElement ene) {
        final ArrayList<NamedParserNode> result = new ArrayList<NamedParserNode>();

        if (!isValidSource(ea.getSource())) {
            return result;
        }

        log.debug("Processing annotations ");
        for (Map.Entry<String, String> pAnnotationDetails : ea.getDetails().entrySet()) {
            final String fName = pAnnotationDetails.getKey();
            // todo externalize
            if (fName.compareToIgnoreCase("appinfo") == 0 || fName.compareToIgnoreCase("value") == 0) {
                log.debug("Annotation content: \n " + pAnnotationDetails.getValue());
                final String content = removeCommentLines(pAnnotationDetails.getValue());
                result.addAll(annotationParser.parse(ene, content));
            }
        }
        return result;
    }

    // removes the lines which start with a //
    private String removeCommentLines(String content) {
        if (content.indexOf("//") == -1) {
            return content;
        }
        final String[] lines = content.split("\n");
        final StringBuilder sb = new StringBuilder();
        for (String line : lines) {
            if (line.trim().startsWith("//")) {
                continue;
            }
            if (sb.length() > 0) {
                sb.append("\n");
            }
            sb.append(line);
        }
        return sb.toString();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.eclipse.emf.teneo.annotations.parser.EClassResolver#getEClass(java
     * .lang.String)
     */
    public EClass getEClass(String name) {
        if (name.startsWith(JPA_PREFIX)) {
            return getEClass(name.substring(JPA_PREFIX.length()));
        }
        return (EClass) PannotationPackage.eINSTANCE.getEClassifier(name);
    }

    /** Is a valid source */
    protected boolean isValidSource(String source) {
        if (source == null) {
            return false;
        }

        if (extraAnnotationsSources.length > 0) {
            for (String annotationSource : extraAnnotationsSources) {
                if (source.equals(annotationSource)) {
                    return true;
                }
            }
        }

        return source.startsWith(Constants.ANNOTATION_SOURCE_TENEO_JPA)
                || source.startsWith(Constants.ANNOTATION_SOURCE_TENEO_MAPPING);
    }

    /** Find the efeature */
    public EStructuralFeature getEStructuralFeature(EClass eClass, String name) {
        return ParserUtil.getEStructuralFeature(eClass, name);
    }

    public void setExtraAnnotationSources(PersistenceOptions po) {
        if (po.getExtraAnnotationSources() != null && po.getExtraAnnotationSources().trim().length() > 0) {
            extraAnnotationsSources = po.getExtraAnnotationSources().split(",");
            for (int i = 0; i < extraAnnotationsSources.length; i++) {
                extraAnnotationsSources[i] = extraAnnotationsSources[i].trim();
                if (extraAnnotationsSources[i].startsWith(Constants.ANNOTATION_SOURCE_TENEO_JPA)
                        || extraAnnotationsSources[i].startsWith(Constants.ANNOTATION_SOURCE_TENEO_MAPPING)) {
                    if (log.isWarnEnabled()) {
                        log.warn("Extra annotation source (" + extraAnnotationsSources[i]
                                + ") starts with the default Teneo annotation source: "
                                + Constants.ANNOTATION_SOURCE_TENEO_JPA + " or "
                                + Constants.ANNOTATION_SOURCE_TENEO_MAPPING
                                + ". Annotations which should sometimes be "
                                + "ignored or disabled should not start with these values as they are always considered by Teneo");
                    }
                }
            }
        }
    }
}