/*******************************************************************************
 * Copyright (c) 2008-2018 Sonatype, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *      Sonatype, Inc. - initial API and implementation
 *******************************************************************************/

package org.eclipse.m2e.editor.pom;

import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.ARTIFACT_ID;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.DEPENDENCY;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.EXTENSION;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.GROUP_ID;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.NAME;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.PARENT;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.PLUGIN;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.PROPERTIES;
import static org.eclipse.m2e.core.ui.internal.editing.PomEdits.VERSION;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.jface.text.hyperlink.IHyperlinkDetector;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.texteditor.MarkerAnnotation;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;

import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.InputLocation;
import org.apache.maven.model.Model;
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.ui.internal.actions.OpenPomAction;
import org.eclipse.m2e.core.ui.internal.util.XmlUtils;


/**
 * @author Eugene Kuleshov
 * @author Milos Kleint
 */
public class PomHyperlinkDetector implements IHyperlinkDetector {
  public IHyperlink[] detectHyperlinks(final ITextViewer textViewer, final IRegion region,
      boolean canShowMultipleHyperlinks) {
    if(region == null || textViewer == null) {
      return null;
    }

    IDocument document = textViewer.getDocument();
    if(document == null) {
      return null;
    }

    IRegion lineInfo;
    String line;
    try {
      lineInfo = document.getLineInformationOfOffset(region.getOffset());
      line = document.get(lineInfo.getOffset(), lineInfo.getLength());
    } catch(BadLocationException ex) {
      return null;
    }

    if(line.length() == 0) {
      return null;
    }
    final List<IHyperlink> hyperlinks = new ArrayList<IHyperlink>();
    final int offset = region.getOffset();

    XmlUtils.performOnCurrentElement(document, offset, (node, structured) -> {
      if(textViewer instanceof ISourceViewer) {
        IHyperlink[] links = openExternalMarkerDefinition((ISourceViewer) textViewer, offset);
        if(links.length > 0) {
          hyperlinks.addAll(Arrays.asList(links));
        }
      }
      //check if we have a property expression at cursor
      IHyperlink link = openPropertyDefinition(node, textViewer, offset);
      if(link != null) {
        hyperlinks.add(link);
      }
      //now check if the dependency/plugin has a version element or not, if not, try searching for it in DM/PM of effective pom
      link = openDPManagement(node, textViewer, offset);
      if(link != null) {
        hyperlinks.add(link);
      }
      //check if <module> text is selected.
      link = openModule(node, textViewer, offset);
      if(link != null) {
        hyperlinks.add(link);
      }
      link = openPOMbyID(node, textViewer, offset);
      if(link != null) {
        hyperlinks.add(link);
      }
    });

    if(hyperlinks.size() > 0) {
      return hyperlinks.toArray(new IHyperlink[0]);
    }
    return null;
  }

  static ManagedArtifactRegion findManagedArtifactRegion(Node current, ITextViewer textViewer, int offset) {
    while(current != null && !(current instanceof Element)) {
      current = current.getParentNode();
    }
    if(current != null) {
      Node artNode = null;
      Node groupNode = null;
      if(ARTIFACT_ID.equals(current.getNodeName())) { //$NON-NLS-1$
        artNode = current;
      }
      if(GROUP_ID.equals(current.getNodeName())) { //$NON-NLS-1$
        groupNode = current;
      }
      //only on artifactid and groupid elements..
      if(artNode == null && groupNode == null) {
        return null;
      }
      Node root = current.getParentNode();
      boolean isDependency = false;
      boolean isPlugin = false;
      if(root != null) {
        String name = root.getNodeName();
        if(DEPENDENCY.equals(name)) { //$NON-NLS-1$
          isDependency = true;
        }
        if(PLUGIN.equals(name)) { //$NON-NLS-1$
          isPlugin = true;
        }
      } else {
        return null;
      }
      if(!isDependency && !isPlugin) {
        //some kind of other identifier
        return null;
      }
      //now see if version is missing
      NodeList childs = root.getChildNodes();
      for(int i = 0; i < childs.getLength(); i++ ) {
        Node child = childs.item(i);
        if(child instanceof Element) {
          Element el = (Element) child;
          if(VERSION.equals(el.getNodeName())) { //$NON-NLS-1$
            return null;
          }
          if(artNode == null && ARTIFACT_ID.equals(el.getNodeName())) { //$NON-NLS-1$
            artNode = el;
          }
          if(groupNode == null && GROUP_ID.equals(el.getNodeName())) { //$NON-NLS-1$
            groupNode = el;
          }
        }
      }
      if(groupNode != null && artNode != null) {
        assert groupNode instanceof IndexedRegion;
        assert artNode instanceof IndexedRegion;

        IndexedRegion groupReg = (IndexedRegion) groupNode;
        IndexedRegion artReg = (IndexedRegion) artNode;
        int startOffset = Math.min(groupReg.getStartOffset(), artReg.getStartOffset());
        int length = Math.max(groupReg.getEndOffset(), artReg.getEndOffset()) - startOffset;
        String groupId = XmlUtils.getTextValue(groupNode);
        String artifactId = XmlUtils.getTextValue(artNode);
        final MavenProject prj = XmlUtils.extractMavenProject(textViewer);
        if(prj != null) {
          //now we can create the region I guess, 
          return new ManagedArtifactRegion(startOffset, length, groupId, artifactId, isDependency, isPlugin, prj);
        }
      }
    }
    return null;
  }

  public static IHyperlink createHyperlink(final ManagedArtifactRegion region) {
    return new IHyperlink() {
      public IRegion getHyperlinkRegion() {
        return region;
      }

      public String getHyperlinkText() {
        return NLS.bind(org.eclipse.m2e.editor.internal.Messages.PomHyperlinkDetector_link_managed,
            "" + region.groupId + ":" + region.artifactId);
      }

      public String getTypeLabel() {
        return "pom-dependency-plugin-management"; //$NON-NLS-1$
      }

      public void open() {
        //see if we can find the plugin in plugin management of resolved project.
        MavenProject mavprj = region.project;
        if(mavprj != null) {
          InputLocation openLocation = findLocationForManagedArtifact(region, mavprj);
          if(openLocation != null) {
            File file = XmlUtils.fileForInputLocation(openLocation, mavprj);
            if(file != null) {
              IFileStore fileStore = EFS.getLocalFileSystem().getStore(file.toURI());
              XMLEditorUtility.openXmlEditor(fileStore, openLocation.getLineNumber(), openLocation.getColumnNumber(),
                  openLocation.getSource().getModelId());
            }
          }
        }
      }
    };

  }

  private IHyperlink openDPManagement(Node current, ITextViewer textViewer, int offset) {
    final ManagedArtifactRegion region = findManagedArtifactRegion(current, textViewer, offset);
    if(region != null) {
      return createHyperlink(region);
    }
    return null;
  }

  static InputLocation findLocationForManagedArtifact(final ManagedArtifactRegion region, MavenProject mavprj) {
    Model mdl = mavprj.getModel();
    InputLocation openLocation = null;
    if(region.isDependency) {
      DependencyManagement dm = mdl.getDependencyManagement();
      if(dm != null) {
        List<Dependency> list = dm.getDependencies();
        String id = region.groupId + ":" + region.artifactId + ":"; //$NON-NLS-1$ //$NON-NLS-2$
        if(list != null) {
          for(Dependency dep : list) {
            if(dep.getManagementKey().startsWith(id)) {
              InputLocation location = dep.getLocation(ARTIFACT_ID); //$NON-NLS-1$
              //when would this be null?
              if(location != null) {
                openLocation = location;
                break;
              }
            }
          }
        }
      }
    }
    if(region.isPlugin) {
      Build build = mdl.getBuild();
      if(build != null) {
        PluginManagement pm = build.getPluginManagement();
        if(pm != null) {
          List<Plugin> list = pm.getPlugins();
          String id = Plugin.constructKey(region.groupId, region.artifactId);
          if(list != null) {
            for(Plugin plg : list) {
              if(id.equals(plg.getKey())) {
                InputLocation location = plg.getLocation(ARTIFACT_ID); //$NON-NLS-1$
                //when would this be null?
                if(location != null) {
                  openLocation = location;
                  break;
                }
              }
            }
          }
        }
      }
    }
    return openLocation;
  }

  static ExpressionRegion findExpressionRegion(Node current, ITextViewer viewer, int offset) {
    if(current != null && current instanceof Text) {
      Text node = (Text) current;
      String value = node.getNodeValue();
      if(value != null) {
        assert node instanceof IndexedRegion;
        IndexedRegion reg = (IndexedRegion) node;
        int index = offset - reg.getStartOffset();
        String before = value.substring(0, Math.min(index + 1, value.length()));
        String after = value.substring(Math.min(index + 1, value.length()));
        int start = before.lastIndexOf("${"); //$NON-NLS-1$
        if(before.lastIndexOf("}") > start) {//$NON-NLS-1$
          //we might be in between two expressions..
          start = -1;
        }
        int end = after.indexOf("}"); //$NON-NLS-1$
        if(after.indexOf("${") != -1 && after.indexOf("${") < end) {//$NON-NLS-1$
          //we might be in between two expressions..
          end = -1;
        }
        if(start > -1 && end > -1) {
          final int startOffset = reg.getStartOffset() + start;
          final String expr = before.substring(start) + after.substring(0, end + 1);
          final int length = expr.length();
          final String prop = before.substring(start + 2) + after.substring(0, end);
// there are often properties that start with project. eg. project.build.sourceEncoding          
//          if (prop.startsWith("project.") || prop.startsWith("pom.")) { //$NON-NLS-1$ //$NON-NLS-2$
//            return null; //ignore these, not in properties section.
//          }
          MavenProject prj = XmlUtils.extractMavenProject(viewer);
          if(prj != null) {
            return new ExpressionRegion(startOffset, length, prop, prj);
          }
        }
      }
    }
    return null;
  }

  public static IHyperlink createHyperlink(final ExpressionRegion region) {
    return new IHyperlink() {
      public IRegion getHyperlinkRegion() {
        return region;
      }

      public String getHyperlinkText() {
        return NLS.bind(org.eclipse.m2e.editor.internal.Messages.PomHyperlinkDetector_open_property, region.property);
      }

      public String getTypeLabel() {
        return "pom-property-expression"; //$NON-NLS-1$
      }

      public void open() {
        //see if we can find the plugin in plugin management of resolved project.
        MavenProject mavprj = region.project;
        if(mavprj != null) {
          //TODO get rid of InputLocation here and use the dom tree to find the property
          Model mdl = mavprj.getModel();
          InputLocation location = null;
          if(mdl.getProperties().containsKey(region.property)) {
            location = mdl.getLocation(PROPERTIES).getLocation(region.property);
          } else if(region.property != null && region.property.startsWith("project.")) {//$NON-NLS-1$
            if("project.version".equals(region.property)) {
              location = mdl.getLocation(VERSION);
            } else if("project.name".equals(region.property)) {
              location = mdl.getLocation(NAME);
            }
          }
          if(location != null) {
            File file = XmlUtils.fileForInputLocation(location, mavprj);
            if(file != null) {
              IFileStore fileStore = EFS.getLocalFileSystem().getStore(file.toURI());
              XMLEditorUtility.openXmlEditor(fileStore, location.getLineNumber(), location.getColumnNumber(),
                  location.getSource().getModelId());
            }
          }
        }
      }
    };
  }

  public static boolean canCreateHyperLink(final ExpressionRegion region) {
    if("project.version".equals(region.property) || "project.name".equals(region.property)) {
      return true;
    }
    return region.project != null && region.project.getModel().getProperties().containsKey(region.property);
  }

  //only create the hyperlink when the origin location for jumping is present.
  //in some cases (managed version comes from imported dependencies) we don't have the location and have nowhere to jump)
  public static boolean canCreateHyperLink(final ManagedArtifactRegion region) {
    return region.project != null
        && PomHyperlinkDetector.findLocationForManagedArtifact(region, region.project) != null;
  }

  static IHyperlink[] openExternalMarkerDefinition(ISourceViewer sourceViewer, int offset) {
    List<IHyperlink> toRet = new ArrayList<IHyperlink>();
    MarkerRegion[] regions = findMarkerRegions(sourceViewer, offset);
    for(MarkerRegion reg : regions) {
      if(reg.isDefinedInParent()) {
        toRet.add(createHyperlink(reg));
      }
    }
    return toRet.toArray(new IHyperlink[0]);
  }

  static MarkerRegion[] findMarkerRegions(ISourceViewer sourceViewer, int offset) {
    List<MarkerRegion> toRet = new ArrayList<MarkerRegion>();
    IAnnotationModel model = sourceViewer.getAnnotationModel();
    if(model != null) { //eg. in tests
      Iterator<Annotation> it = model.getAnnotationIterator();
      while(it.hasNext()) {
        Annotation ann = it.next();
        if(ann instanceof MarkerAnnotation) {
          Position pos = sourceViewer.getAnnotationModel().getPosition(ann);
          if(pos.includes(offset)) {
            toRet.add(new MarkerRegion(pos.getOffset(), pos.getLength(), (MarkerAnnotation) ann));
          }
        }
      }
    }
    return toRet.toArray(new MarkerRegion[0]);
  }

  public static IHyperlink createHyperlink(final MarkerRegion mark) {
    return new IHyperlink() {

      public IRegion getHyperlinkRegion() {
        return new Region(mark.getOffset(), mark.getLength());
      }

      public String getTypeLabel() {
        return "marker-error-defined-in-parent"; //$NON-NLS-1$;
      }

      public String getHyperlinkText() {
        return NLS.bind("Open definition in parent for {0}", mark.getAnnotation().getText()); //TODO if there are multiple markers in one spot, how to differentiate better..
      }

      public void open() {
        IMarker marker = mark.getAnnotation().getMarker();
        String loc = marker.getAttribute(IMavenConstants.MARKER_CAUSE_RESOURCE_PATH, null);
        if(loc != null) {
          IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(loc));
          int row = marker.getAttribute(IMavenConstants.MARKER_CAUSE_LINE_NUMBER, 0);
          int column = marker.getAttribute(IMavenConstants.MARKER_CAUSE_COLUMN_START, 0);
          String name = marker.getAttribute(IMavenConstants.MARKER_CAUSE_RESOURCE_ID, null);
//          String hint = marker.getAttribute(IMavenConstants.MARKER_ATTR_EDITOR_HINT, null);
//          if (IMavenConstants.EDITOR_HINT_NOT_COVERED_MOJO_EXECUTION.equals(hint)) {
//          }
          XMLEditorUtility.openXmlEditor(fileStore, row, column, name);
        }
      }
    };
  }

  private IHyperlink openPropertyDefinition(Node current, ITextViewer viewer, int offset) {
    final ExpressionRegion region = findExpressionRegion(current, viewer, offset);
    if(region != null && canCreateHyperLink(region)) {
      return createHyperlink(region);
    }
    return null;
  }

  private IHyperlink openModule(Node current, ITextViewer textViewer, int offset) {
    while(current != null && !(current instanceof Element)) {
      current = current.getParentNode();
    }
    if(current == null) {
      return null;
    }
    String pathUp = XmlUtils.pathUp(current, 2);
    if(!"modules/module".equals(pathUp)) { //$NON-NLS-1$
      //just in case we are in some random plugin configuration snippet..
      return null;
    }

    ITextFileBuffer buf = FileBuffers.getTextFileBufferManager().getTextFileBuffer(textViewer.getDocument());
    if(buf == null) {
      //for repository based poms..
      return null;
    }
    IFileStore folder = buf.getFileStore().getParent();

    String path = XmlUtils.getTextValue(current);
    final String fPath = path;
    //construct IPath for the child pom file, handle relative paths..
    while(folder != null && path.startsWith("../")) { //$NON-NLS-1$
      folder = folder.getParent();
      path = path.substring("../".length());//$NON-NLS-1$
    }
    if(folder == null) {
      return null;
    }
    IFileStore modulePom = folder.getChild(path);
    if(!modulePom.getName().endsWith("xml")) { //$NON-NLS-1$
      modulePom = modulePom.getChild("pom.xml");//$NON-NLS-1$
    }
    final IFileStore fileStore = modulePom;
    if(!fileStore.fetchInfo().exists()) {
      return null;
    }
    assert current instanceof IndexedRegion;
    final IndexedRegion region = (IndexedRegion) current;

    return new IHyperlink() {
      public IRegion getHyperlinkRegion() {
        return new Region(region.getStartOffset(), region.getEndOffset() - region.getStartOffset());
      }

      public String getHyperlinkText() {
        return NLS.bind(org.eclipse.m2e.editor.internal.Messages.PomHyperlinkDetector_open_module, fPath);
      }

      public String getTypeLabel() {
        return "pom-module"; //$NON-NLS-1$
      }

      public void open() {
        XMLEditorUtility.openXmlEditor(fileStore);
      }
    };
  }

  private IHyperlink openPOMbyID(Node current, final ITextViewer viewer, int offset) {
    while(current != null && !(current instanceof Element)) {
      current = current.getParentNode();
    }
    if(current == null) {
      return null;
    }
    current = current.getParentNode();
    if(current == null || !(current instanceof Element)) {
      return null;
    }
    Element parent = (Element) current;
    String parentName = parent.getNodeName();
    if(DEPENDENCY.equals(parentName) || PARENT.equals(parentName) || PLUGIN.equals(parentName)
        || "reportPlugin".equals(parentName) || EXTENSION.equals(parentName)) {
      final Node groupId = XmlUtils.findChild(parent, GROUP_ID);
      final Node artifactId = XmlUtils.findChild(parent, ARTIFACT_ID);
      final Node version = XmlUtils.findChild(parent, VERSION);
      final MavenProject prj = XmlUtils.extractMavenProject(viewer);

      IHyperlink pomHyperlink = new IHyperlink() {
        public IRegion getHyperlinkRegion() {
          //the goal here is to have the groupid/artifactid/version combo underscored by the link.
          //that will prevent underscoring big portions (like plugin config) underscored and
          // will also handle cases like dependencies within plugins.
          int max = groupId != null ? ((IndexedRegion) groupId).getEndOffset() : Integer.MIN_VALUE;
          int min = groupId != null ? ((IndexedRegion) groupId).getStartOffset() : Integer.MAX_VALUE;
          max = Math.max(max, artifactId != null ? ((IndexedRegion) artifactId).getEndOffset() : Integer.MIN_VALUE);
          min = Math.min(min, artifactId != null ? ((IndexedRegion) artifactId).getStartOffset() : Integer.MAX_VALUE);
          max = Math.max(max, version != null ? ((IndexedRegion) version).getEndOffset() : Integer.MIN_VALUE);
          min = Math.min(min, version != null ? ((IndexedRegion) version).getStartOffset() : Integer.MAX_VALUE);
          return new Region(min, max - min);
        }

        public String getHyperlinkText() {
          return NLS.bind(org.eclipse.m2e.editor.internal.Messages.PomHyperlinkDetector_hyperlink_pattern,
              XmlUtils.getTextValue(groupId), XmlUtils.getTextValue(artifactId));
        }

        public String getTypeLabel() {
          return "pom"; //$NON-NLS-1$
        }

        public void open() {
          new Job(org.eclipse.m2e.editor.internal.Messages.PomHyperlinkDetector_job_name) {
            protected IStatus run(IProgressMonitor monitor) {
              // TODO resolve groupId if groupId==null
              String gridString = groupId == null ? "org.apache.maven.plugins" : XmlUtils.getTextValue(groupId); //$NON-NLS-1$      
              String artidString = artifactId == null ? null : XmlUtils.getTextValue(artifactId);
              String versionString = version == null ? null : XmlUtils.getTextValue(version);
              if(prj != null && gridString != null && artidString != null
                  && (versionString == null || versionString.contains("${"))) { //$NON-NLS-1$
                try {
                  //TODO how do we decide here if the hyperlink is a dependency or a plugin
                  // hyperlink??
                  versionString = PomTemplateContext.extractVersion(prj, null, versionString, gridString, artidString,
                      PomTemplateContext.EXTRACT_STRATEGY_DEPENDENCY);

                } catch(CoreException e) {
                  versionString = null;
                }
              }
              if(versionString == null) {
                return Status.OK_STATUS;
              }
              OpenPomAction.openEditor(gridString, artidString, versionString, prj, monitor);
// TODO: it's preferable to open the xml page, but this code will blink and open overview first and later switch. looks bad            
//            Display.getDefault().syncExec(new Runnable() {
//              public void run() {
//                selectEditorPage(page);
//              }
//            });
              return Status.OK_STATUS;
            }
          }.schedule();
        }

      };
      return pomHyperlink;
    }
    return null;
  }

  public static class ExpressionRegion implements IRegion {

    final String property;

    private int length;

    private int offset;

    final MavenProject project;

    public ExpressionRegion(int startOffset, int length, String prop, MavenProject project) {
      this.offset = startOffset;
      this.length = length;
      this.property = prop;
      this.project = project;
      assert project != null;
    }

    public int getLength() {
      return length;
    }

    public int getOffset() {
      return offset;
    }
  }

  public static class ManagedArtifactRegion implements IRegion {

    private int length;

    private int offset;

    final MavenProject project;

    final String groupId;

    final String artifactId;

    final boolean isPlugin;

    final boolean isDependency;

    public ManagedArtifactRegion(int startOffset, int length, String groupId, String artifactId, boolean isDependency,
        boolean isPlugin, MavenProject project) {
      this.offset = startOffset;
      this.length = length;
      this.project = project;
      assert project != null;
      this.artifactId = artifactId;
      this.groupId = groupId;
      this.isDependency = isDependency;
      this.isPlugin = isPlugin;
    }

    public int getLength() {
      return length;
    }

    public int getOffset() {
      return offset;
    }
  }

  public static class MarkerRegion implements IRegion {

    private final MarkerAnnotation ann;

    final int offset;

    final int length;

    public MarkerRegion(int offset, int length, MarkerAnnotation applicable) {
      this.offset = offset;
      this.length = length;
      this.ann = applicable;
    }

    public int getLength() {
      return length;
    }

    public int getOffset() {
      return offset;
    }

    public MarkerAnnotation getAnnotation() {
      return ann;
    }

    public boolean isDefinedInParent() {
      IMarker mark = ann.getMarker();
      String isElsewhere = mark.getAttribute(IMavenConstants.MARKER_CAUSE_RESOURCE_PATH, null);
      if(isElsewhere != null) {
        return true;
      }
      return false;
    }

  }

}
