org.eclipse.m2e.editor.xml.internal.MarkerLocationService.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.m2e.editor.xml.internal.MarkerLocationService.java

Source

/*******************************************************************************
 * Copyright (c) 2008-2010 Sonatype, Inc.
 * 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:
 *      Sonatype, Inc. - initial API and implementation
 *      Rob Newton - added warning preferences page for disabling warnings
 *******************************************************************************/

package org.eclipse.m2e.editor.xml.internal;

import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.childEquals;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.childMissingOrEqual;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.findChild;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.findChilds;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.getTextValue;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.textEquals;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.w3c.dom.Comment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.osgi.util.NLS;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.xml.core.internal.parser.regions.TagNameRegion;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;

import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.project.MavenProject;

import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.m2e.core.internal.markers.IEditorMarkerService;
import org.eclipse.m2e.core.internal.markers.IMarkerLocationService;
import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager;
import org.eclipse.m2e.core.internal.preferences.MavenPreferenceConstants;
import org.eclipse.m2e.core.ui.internal.M2EUIPluginActivator;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits;
import org.eclipse.m2e.core.ui.internal.editing.PomEdits.Matcher;

/**
 * a service impl used by the core module to improve marker locations and addition of our own markers
 * 
 * @author mkleint
 */
@SuppressWarnings("restriction")
public class MarkerLocationService implements IMarkerLocationService, IEditorMarkerService {
    private static final Logger log = LoggerFactory.getLogger(MarkerLocationService.class);

    private static final String XSI_SCHEMA_LOCATION = "xsi:schemaLocation"; //$NON-NLS-1$

    private static final String PROJECT_NODE = "project"; //$NON-NLS-1$

    private static final String OFFSET = "offset"; //$NON-NLS-1$

    public void findLocationForMarker(final IMarker marker) {
        IDOMModel domModel = null;
        try {
            Integer lineNumber = (Integer) marker.getAttribute(IMarker.LINE_NUMBER);
            if (lineNumber == null) {
                return;
            }
            Integer columnStart = (Integer) marker.getAttribute(IMavenConstants.MARKER_COLUMN_START);
            if (columnStart == null) {
                return;
            }
            Integer columnEnd = (Integer) marker.getAttribute(IMavenConstants.MARKER_COLUMN_END);
            if (columnEnd == null) {
                return;
            }

            IFile resource = (IFile) marker.getResource();
            domModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForRead(resource);
            if (domModel == null) {
                throw new IllegalArgumentException("Document is not structured: " + resource);
            }
            IStructuredDocument document = domModel.getStructuredDocument();
            int charStart = document.getLineOffset(lineNumber - 1) + columnStart - 1;
            marker.setAttribute(IMarker.CHAR_START, charStart);
            int charEnd;
            if (columnEnd > columnStart) {
                charEnd = document.getLineOffset(lineNumber - 1) + columnEnd;
            } else {
                IRegion line = document.getLineInformation(lineNumber - 1);
                charEnd = line.getOffset() + line.getLength();
            }
            marker.setAttribute(IMarker.CHAR_END, charEnd);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (domModel != null) {
                domModel.releaseFromRead();
            }
        }
    }

    public void findLocationForMarker_(final IMarker marker) {

        String hint = marker.getAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT, null);

        if (IMavenConstants.EDITOR_HINT_NOT_COVERED_MOJO_EXECUTION.equals(hint)) {
            try {
                final boolean lookInPM = false;
                final String groupId = marker.getAttribute(IMavenConstants.MARKER_ATTR_GROUP_ID, "");
                final String artifactId = marker.getAttribute(IMavenConstants.MARKER_ATTR_ARTIFACT_ID, "");
                final String exec = marker.getAttribute(IMavenConstants.MARKER_ATTR_EXECUTION_ID, "");
                final String goal = marker.getAttribute(IMavenConstants.MARKER_ATTR_GOAL, "");
                XmlUtils.performOnRootElement((IFile) marker.getResource(), new NodeOperation<Element>() {
                    public void process(Element root, IStructuredDocument structuredDocument) {
                        Element build = findChild(root, PomEdits.BUILD);
                        List<Element> candidates = new ArrayList<Element>();
                        Element plugin = findPlugin(build, groupId, artifactId);
                        if (plugin != null) {
                            candidates.add(plugin);
                        }
                        if (lookInPM) {
                            plugin = findPlugin(findChild(build, PomEdits.PLUGIN_MANAGEMENT), groupId, artifactId);
                            if (plugin != null) {
                                candidates.add(plugin);
                            }
                        }
                        //look in profiles
                        List<Element> profiles = findChilds(findChild(root, PomEdits.PROFILES), PomEdits.PROFILE);
                        //TODO eventually we should only process the activated profiles.. but need MavenProject for it.
                        for (Element profile : profiles) {
                            Element profBuild = findChild(profile, PomEdits.BUILD);
                            plugin = findPlugin(profBuild, groupId, artifactId);
                            if (plugin != null) {
                                candidates.add(plugin);
                            }
                            if (lookInPM) {
                                plugin = findPlugin(findChild(profBuild, PomEdits.PLUGIN_MANAGEMENT), groupId,
                                        artifactId);
                                if (plugin != null) {
                                    candidates.add(plugin);
                                }
                            }
                        }
                        Element ourMarkerPlacement = null;
                        for (Element candid : candidates) {
                            Matcher match = exec.equals("default") ? childMissingOrEqual(PomEdits.ID, "default")
                                    : childEquals(PomEdits.ID, exec);
                            Element execution = findChild(findChild(candid, PomEdits.EXECUTIONS),
                                    PomEdits.EXECUTION, match);
                            if (execution != null) {
                                Element goalEl = findChild(findChild(execution, PomEdits.GOALS), PomEdits.GOAL,
                                        textEquals(goal));
                                if (goalEl != null) {
                                    ourMarkerPlacement = goalEl;
                                    break;
                                } else {
                                    //only remember the first execution match
                                    if (ourMarkerPlacement == null) {
                                        ourMarkerPlacement = findChild(execution, PomEdits.ID);
                                        if (ourMarkerPlacement == null) { //just old plain paranoia
                                            ourMarkerPlacement = execution;
                                        }
                                    }
                                }
                            }
                        }
                        if (ourMarkerPlacement == null) {
                            plugin = candidates.size() > 0 ? candidates.get(0) : null;
                            //executions not here (eg. in PM or parent PM), just mark the plugin's artifactId
                            ourMarkerPlacement = findChild(plugin, PomEdits.ARTIFACT_ID);
                            if (ourMarkerPlacement == null && plugin != null) { //just old plain paranoia
                                ourMarkerPlacement = plugin;
                            } else {
                                //what are the strategies for placement when no plugin is found?
                                // we could.. search pluginManagement, but it's unlikely to be there..
                                ourMarkerPlacement = build != null ? build : root;
                            }
                        }

                        annotateMarker(marker, structuredDocument, ourMarkerPlacement);
                    }

                    private Element findPlugin(Element build, String groupId, String artifactId) {
                        Matcher grIdmatch = groupId.equals("org.apache.maven.plugins")
                                ? childMissingOrEqual(PomEdits.GROUP_ID, groupId)
                                : childEquals(PomEdits.GROUP_ID, groupId);
                        return findChild(findChild(build, PomEdits.PLUGINS), PomEdits.PLUGIN, grIdmatch,
                                childEquals(PomEdits.ARTIFACT_ID, artifactId));
                    }
                });
            } catch (IOException e) {
                log.error("Error locating marker", e);
            } catch (CoreException e) {
                log.error("Error locating marker", e);
            }
        }
    }

    private void annotateMarker(final IMarker marker, IStructuredDocument structuredDocument,
            Element ourMarkerPlacement) {
        if (ourMarkerPlacement instanceof IndexedRegion) {
            IndexedRegion region = (IndexedRegion) ourMarkerPlacement;
            try {
                marker.setAttribute(IMarker.CHAR_START, region.getStartOffset());
                //as end, mark just the end of line where the region starts to prevent marking the entire <build> section.
                IRegion line;
                try {
                    line = structuredDocument.getLineInformationOfOffset(region.getStartOffset());
                    int end = Math.min(region.getEndOffset(), line.getOffset() + line.getLength());
                    marker.setAttribute(IMarker.CHAR_END, end);
                } catch (BadLocationException e) {
                    marker.setAttribute(IMarker.CHAR_END, region.getStartOffset() + region.getLength());
                }
                marker.setAttribute(IMarker.LINE_NUMBER,
                        structuredDocument.getLineOfOffset(region.getStartOffset()) + 1);
            } catch (CoreException e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    public void addEditorHintMarkers(IMavenMarkerManager markerManager, IFile pom, MavenProject mavenProject,
            String type) {
        checkForSchema(markerManager, pom, type);
        checkVarious(markerManager, pom, mavenProject, type);
    }

    /**
     * The xsi:schema info is not part of the model, it is stored in the xml only. Need to open the DOM and look for the
     * project node to see if it has this schema defined
     * 
     * @param mavenMarkerManager
     * @param pomFile
     */
    static void checkForSchema(IMavenMarkerManager mavenMarkerManager, IResource pomFile, String type) {
        IDOMModel domModel = null;
        try {
            if (!(pomFile instanceof IFile)) {
                return;
            }
            domModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForRead((IFile) pomFile);
            IStructuredDocument document = domModel.getStructuredDocument();

            // iterate through document regions
            documentLoop: for (IStructuredDocumentRegion documentRegion : document.getStructuredDocumentRegions()) {
                // only check tag regions
                if (DOMRegionContext.XML_TAG_NAME.equals(documentRegion.getType())) {
                    for (ITextRegion textRegion : documentRegion.getRegions().toArray()) {
                        // find a project tag
                        if (textRegion instanceof TagNameRegion
                                && PROJECT_NODE.equals(documentRegion.getText(textRegion))) {
                            // check if schema is missing
                            if (documentRegion.getText().lastIndexOf(XSI_SCHEMA_LOCATION) == -1) {
                                int offset = documentRegion.getStartOffset();
                                int lineNumber = document.getLineOfOffset(offset) + 1;
                                IMarker marker = mavenMarkerManager.addMarker(pomFile, type,
                                        org.eclipse.m2e.core.internal.Messages.MavenMarkerManager_error_noschema,
                                        lineNumber, IMarker.SEVERITY_WARNING);
                                //the quick fix in the marker view needs to know the offset, since it doesn't have access to the
                                //editor/source viewer
                                if (marker != null) {
                                    marker.setAttribute(OFFSET, offset);
                                    marker.setAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT,
                                            IMavenConstants.EDITOR_HINT_MISSING_SCHEMA);
                                    marker.setAttribute(IMarker.CHAR_START, documentRegion.getStartOffset());
                                    marker.setAttribute(IMarker.CHAR_END, documentRegion.getEndOffset());
                                    marker.setAttribute("problemType", "pomhint"); //only imporant in case we enable the generic xml quick fixes //$NON-NLS-1$ //$NON-NLS-2$
                                }
                            }
                            // there could only be one project tag
                            break documentLoop;
                        }
                    }
                }
            }
        } catch (Exception ex) {
            log.error("Error checking for schema", ex); //$NON-NLS-1$
        } finally {
            if (domModel != null) {
                domModel.releaseFromRead();
            }
        }
    }

    private static void checkManagedDependencies(IMavenMarkerManager mavenMarkerManager, Element root,
            IResource pomFile, MavenProject mavenproject, String type, IStructuredDocument document)
            throws CoreException {
        List<Element> candidates = new ArrayList<Element>();

        Element dependencies = findChild(root, PomEdits.DEPENDENCIES);
        if (dependencies != null) {
            for (Element el : findChilds(dependencies, PomEdits.DEPENDENCY)) {
                Element version = findChild(el, PomEdits.VERSION);
                if (version != null) {
                    candidates.add(el);
                }
            }
        }
        //we should also consider <dependencies> section in the profiles, but profile are optional and so is their
        // dependencyManagement section.. that makes handling our markers more complex.
        // see MavenProject.getInjectedProfileIds() for a list of currently active profiles in effective pom
        String currentProjectKey = mavenproject.getGroupId() + ":" + mavenproject.getArtifactId() + ":" //$NON-NLS-1$//$NON-NLS-2$
                + mavenproject.getVersion();
        List<String> activeprofiles = mavenproject.getInjectedProfileIds().get(currentProjectKey);
        //remember what profile we found the dependency in.
        Map<Element, String> candidateProfile = new HashMap<Element, String>();
        Element profiles = findChild(root, PomEdits.PROFILES);
        if (profiles != null) {
            for (Element profile : findChilds(profiles, PomEdits.PROFILE)) {
                String idString = getTextValue(findChild(profile, PomEdits.ID));
                if (idString != null && activeprofiles.contains(idString)) {
                    dependencies = findChild(profile, PomEdits.DEPENDENCIES);
                    if (dependencies != null) {
                        for (Element el : findChilds(dependencies, PomEdits.DEPENDENCY)) {
                            Element version = findChild(el, PomEdits.VERSION);
                            if (version != null) {
                                candidates.add(el);
                                candidateProfile.put(el, idString);
                            }
                        }
                    }
                }
            }
        }
        //collect the managed dep ids
        Map<String, String> managed = new HashMap<String, String>();
        DependencyManagement dm = mavenproject.getDependencyManagement();
        if (dm != null) {
            List<Dependency> deps = dm.getDependencies();
            if (deps != null) {
                for (Dependency dep : deps) {
                    if (dep.getVersion() != null) { //#335366
                        //shall we be using geManagementkey() here? but it contains also the type, not only the gr+art ids..
                        managed.put(dep.getGroupId() + ":" + dep.getArtifactId(), dep.getVersion()); //$NON-NLS-1$
                    }
                }
            }
        }

        //now we have all the candidates, match them against the effective managed set 
        for (Element dep : candidates) {
            Element version = findChild(dep, PomEdits.VERSION);
            String grpString = getTextValue(findChild(dep, PomEdits.GROUP_ID));
            String artString = getTextValue(findChild(dep, PomEdits.ARTIFACT_ID));
            String versionString = getTextValue(version);
            if (grpString != null && artString != null && versionString != null) {
                String id = grpString + ":" + artString; //$NON-NLS-1$
                if (managed.containsKey(id)) {
                    String managedVersion = managed.get(id);
                    if (version instanceof IndexedRegion) {
                        IndexedRegion off = (IndexedRegion) version;
                        if (lookForIgnoreMarker(document, version, off, IMavenConstants.MARKER_IGNORE_MANAGED)) {
                            continue;
                        }

                        IMarker mark = mavenMarkerManager.addMarker(pomFile, type,
                                NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenMarkerManager_managed_title,
                                        managedVersion, artString),
                                document.getLineOfOffset(off.getStartOffset()) + 1, IMarker.SEVERITY_WARNING);
                        mark.setAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT,
                                IMavenConstants.EDITOR_HINT_MANAGED_DEPENDENCY_OVERRIDE);
                        mark.setAttribute(IMarker.CHAR_START, off.getStartOffset());
                        mark.setAttribute(IMarker.CHAR_END, off.getEndOffset());
                        mark.setAttribute("problemType", "pomhint"); //only imporant in case we enable the generic xml quick fixes //$NON-NLS-1$ //$NON-NLS-2$
                        //add these attributes to easily and deterministicaly find the declaration in question
                        mark.setAttribute("groupId", grpString); //$NON-NLS-1$
                        mark.setAttribute("artifactId", artString); //$NON-NLS-1$
                        String profile = candidateProfile.get(dep);
                        if (profile != null) {
                            mark.setAttribute("profile", profile); //$NON-NLS-1$
                        }
                    }
                }
            }
        }
    }

    private static void checkManagedPlugins(IMavenMarkerManager mavenMarkerManager, Element root, IResource pomFile,
            MavenProject mavenproject, String type, IStructuredDocument document) throws CoreException {
        List<Element> candidates = new ArrayList<Element>();
        Element build = findChild(root, PomEdits.BUILD);
        if (build == null) {
            return;
        }
        Element plugins = findChild(build, PomEdits.PLUGINS);
        if (plugins != null) {
            for (Element el : findChilds(plugins, PomEdits.PLUGIN)) {
                Element version = findChild(el, PomEdits.VERSION);
                if (version != null) {
                    candidates.add(el);
                }
            }
        }
        //we should also consider <plugins> section in the profiles, but profile are optional and so is their
        // pluginManagement section.. that makes handling our markers more complex.
        // see MavenProject.getInjectedProfileIds() for a list of currently active profiles in effective pom
        String currentProjectKey = mavenproject.getGroupId() + ":" + mavenproject.getArtifactId() + ":" //$NON-NLS-1$//$NON-NLS-2$
                + mavenproject.getVersion();
        List<String> activeprofiles = mavenproject.getInjectedProfileIds().get(currentProjectKey);
        //remember what profile we found the dependency in.
        Map<Element, String> candidateProfile = new HashMap<Element, String>();
        Element profiles = findChild(root, PomEdits.PROFILES);
        if (profiles != null) {
            for (Element profile : findChilds(profiles, PomEdits.PROFILE)) {
                String idString = getTextValue(findChild(profile, PomEdits.ID));
                if (idString != null && activeprofiles.contains(idString)) {
                    build = findChild(profile, PomEdits.BUILD);
                    if (build == null) {
                        continue;
                    }
                    plugins = findChild(build, PomEdits.PLUGINS);
                    if (plugins != null) {
                        for (Element el : findChilds(plugins, PomEdits.PLUGIN)) {
                            Element version = findChild(el, PomEdits.VERSION);
                            if (version != null) {
                                candidates.add(el);
                                candidateProfile.put(el, idString);
                            }
                        }
                    }
                }
            }
        }
        //collect the managed plugin ids
        Map<String, String> managed = new HashMap<String, String>();
        PluginManagement pm = mavenproject.getPluginManagement();
        if (pm != null) {
            List<Plugin> plgs = pm.getPlugins();
            if (plgs != null) {
                for (Plugin plg : plgs) {
                    InputLocation loc = plg.getLocation("version");
                    //#350203 skip plugins defined in the superpom
                    if (loc != null) {
                        managed.put(plg.getKey(), plg.getVersion());
                    }
                }
            }
        }

        //now we have all the candidates, match them against the effective managed set 
        for (Element dep : candidates) {
            String grpString = getTextValue(findChild(dep, PomEdits.GROUP_ID)); //$NON-NLS-1$
            if (grpString == null) {
                grpString = "org.apache.maven.plugins"; //$NON-NLS-1$
            }
            String artString = getTextValue(findChild(dep, PomEdits.ARTIFACT_ID)); //$NON-NLS-1$
            Element version = findChild(dep, PomEdits.VERSION); //$NON-NLS-1$
            String versionString = getTextValue(version);
            if (artString != null && versionString != null) {
                String id = Plugin.constructKey(grpString, artString);
                if (managed.containsKey(id)) {
                    String managedVersion = managed.get(id);
                    if (version instanceof IndexedRegion) {
                        IndexedRegion off = (IndexedRegion) version;
                        if (lookForIgnoreMarker(document, version, off, IMavenConstants.MARKER_IGNORE_MANAGED)) {
                            continue;
                        }

                        IMarker mark = mavenMarkerManager.addMarker(pomFile, type,
                                NLS.bind(org.eclipse.m2e.core.internal.Messages.MavenMarkerManager_managed_title,
                                        managedVersion, artString),
                                document.getLineOfOffset(off.getStartOffset()) + 1, IMarker.SEVERITY_WARNING);
                        mark.setAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT,
                                IMavenConstants.EDITOR_HINT_MANAGED_PLUGIN_OVERRIDE);
                        mark.setAttribute(IMarker.CHAR_START, off.getStartOffset());
                        mark.setAttribute(IMarker.CHAR_END, off.getEndOffset());
                        mark.setAttribute("problemType", "pomhint"); //only imporant in case we enable the generic xml quick fixes //$NON-NLS-1$ //$NON-NLS-2$
                        //add these attributes to easily and deterministicaly find the declaration in question
                        mark.setAttribute("groupId", grpString); //$NON-NLS-1$
                        mark.setAttribute("artifactId", artString); //$NON-NLS-1$
                        String profile = candidateProfile.get(dep);
                        if (profile != null) {
                            mark.setAttribute("profile", profile); //$NON-NLS-1$
                        }
                    }
                }
            }
        }
    }

    private static void checkParentMatchingGroupIdVersion(IMavenMarkerManager mavenMarkerManager, Element root,
            IResource pomFile, String type, IStructuredDocument document) throws CoreException {
        Element parent = findChild(root, PomEdits.PARENT);
        Element groupId = findChild(root, PomEdits.GROUP_ID);
        if (parent != null && groupId != null && !skipParentMatchingGroupIdWarning()) {
            //now compare the values of parent and project groupid..
            String parentString = getTextValue(findChild(parent, PomEdits.GROUP_ID));
            String childString = getTextValue(groupId);
            if (parentString != null && parentString.equals(childString)) {
                //now figure out the offset
                if (groupId instanceof IndexedRegion) {
                    IndexedRegion off = (IndexedRegion) groupId;
                    IMarker mark = mavenMarkerManager.addMarker(pomFile, type,
                            org.eclipse.m2e.core.internal.Messages.MavenMarkerManager_duplicate_groupid,
                            document.getLineOfOffset(off.getStartOffset()) + 1, IMarker.SEVERITY_WARNING);
                    mark.setAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT,
                            IMavenConstants.EDITOR_HINT_PARENT_GROUP_ID);
                    mark.setAttribute(IMarker.CHAR_START, off.getStartOffset());
                    mark.setAttribute(IMarker.CHAR_END, off.getEndOffset());
                    mark.setAttribute("problemType", "pomhint"); //only important in case we enable the generic xml quick fixes //$NON-NLS-1$ //$NON-NLS-2$
                }
            }
        }
        Element version = findChild(root, PomEdits.VERSION); //$NON-NLS-1$
        if (parent != null && version != null && !skipParentMatchingVersionWarning()) {
            //now compare the values of parent and project version..
            String parentString = getTextValue(findChild(parent, PomEdits.VERSION)); //$NON-NLS-1$
            String childString = getTextValue(version);
            if (parentString != null && parentString.equals(childString)) {
                //now figure out the offset
                if (version instanceof IndexedRegion) {
                    IndexedRegion off = (IndexedRegion) version;
                    IMarker mark = mavenMarkerManager.addMarker(pomFile, type,
                            org.eclipse.m2e.core.internal.Messages.MavenMarkerManager_duplicate_version,
                            document.getLineOfOffset(off.getStartOffset()) + 1, IMarker.SEVERITY_WARNING);
                    mark.setAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT,
                            IMavenConstants.EDITOR_HINT_PARENT_VERSION);
                    mark.setAttribute(IMarker.CHAR_START, off.getStartOffset());
                    mark.setAttribute(IMarker.CHAR_END, off.getEndOffset());
                    mark.setAttribute("problemType", "pomhint"); //only important in case we enable the generic xml quick fixes //$NON-NLS-1$ //$NON-NLS-2$
                }
            }
        }
    }

    private static boolean skipParentMatchingGroupIdWarning() {
        return M2EUIPluginActivator.getDefault().getPreferenceStore()
                .getBoolean(MavenPreferenceConstants.P_DISABLE_GROUPID_DUP_OF_PARENT_WARNING);
    }

    private static boolean skipParentMatchingVersionWarning() {
        return M2EUIPluginActivator.getDefault().getPreferenceStore()
                .getBoolean(MavenPreferenceConstants.P_DISABLE_VERSION_DUP_OF_PARENT_WARNING);
    }

    /**
     * @param mavenMarkerManager
     * @param pomFile
     * @param mavenProject can be null
     */
    static void checkVarious(IMavenMarkerManager mavenMarkerManager, IResource pomFile, MavenProject mavenProject,
            String type) {
        IDOMModel domModel = null;
        try {
            if (!(pomFile instanceof IFile)) {
                return;
            }
            domModel = (IDOMModel) StructuredModelManager.getModelManager().getModelForRead((IFile) pomFile);
            IStructuredDocument document = domModel.getStructuredDocument();
            Element root = domModel.getDocument().getDocumentElement();

            if (root.getNodeName().equals("project")) { //$NON-NLS-1$
                //now check parent version and groupid against the current project's ones..
                checkParentMatchingGroupIdVersion(mavenMarkerManager, root, pomFile, type, document);
                if (mavenProject != null) {
                    checkManagedDependencies(mavenMarkerManager, root, pomFile, mavenProject, type, document);
                    checkManagedPlugins(mavenMarkerManager, root, pomFile, mavenProject, type, document);
                }
            }
        } catch (Exception t) {
            log.error("Error checking for warnings", t); //$NON-NLS-1$
        } finally {
            if (domModel != null) {
                domModel.releaseFromRead();
            }
        }
    }

    private static boolean lookForIgnoreMarker(IStructuredDocument document, Element version, IndexedRegion off,
            String ignoreString) {
        Node reg = version;
        int line = document.getLineOfOffset(off.getStartOffset());
        try {
            int lineend = document.getLineOffset(line) + document.getLineLength(line) - 1;
            int start = off.getStartOffset();
            while (reg != null && start < lineend) {
                reg = reg.getNextSibling();
                if (reg != null && reg instanceof Comment) {
                    Comment comm = (Comment) reg;
                    String data = comm.getData();
                    if (data != null && data.contains(ignoreString)) {
                        return true;
                    }
                }
                if (reg != null) {
                    start = ((IndexedRegion) reg).getStartOffset();
                }
            }
        } catch (BadLocationException ex) {
            //not possible IMHO we ask for line offset of line we know is in the document.
        }
        return false;
    }

}