Package qwickie.hyperlink

Source Code of qwickie.hyperlink.WicketHyperlink

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 qwickie.hyperlink;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.ui.actions.OpenNewClassWizardAction;
import org.eclipse.jdt.ui.wizards.NewClassWizardPage;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.ITextEditor;

import qwickie.QWickieActivator;
import qwickie.util.DocumentHelper;
import qwickie.util.FileSearcher;
import qwickie.util.TypeHelper;

/**
* @author count.negative
*
*/
public class WicketHyperlink implements IHyperlink {

  public static final String JAVA = "java";
  public static final String HTML = "html";
  public static final String PROPERTIES = "properties";
  public static final String XML = "xml";
  public static final String XML_PROPERTIES = "properties.xml";

  private String wicketId;
  private final IRegion region;
  private final String extension;
  private boolean found;
  private boolean openJavaFileOnly;

  public WicketHyperlink(final IRegion region, final String wicketId, final String extension) {
    Assert.isNotNull(wicketId);
    Assert.isNotNull(region);
    Assert.isNotNull(extension);

    this.region = region;
    this.wicketId = wicketId;
    this.extension = extension;
  }

  public IRegion getHyperlinkRegion() {
    return this.region;
  }

  public void open() {
    if (this.wicketId != null) {
      final IWorkbench workbench = PlatformUI.getWorkbench();
      final IWorkbenchPage activePage = workbench.getActiveWorkbenchWindow().getActivePage();
      final IEditorInput editorInput = activePage.getActiveEditor().getEditorInput();
      final IResource openedResource = (IResource) editorInput.getAdapter(IResource.class);
      final List<String> toOpenFilenames = getFilenamesToOpen(openedResource, extension);
      boolean foundInPropertiesFile = false;

      for (final String toOpenFilename : toOpenFilenames) {
        if (!samePackage(FileSearcher.removeSourceFolder(openedResource.getProject(), openedResource.getFullPath().toPortableString()), FileSearcher.removeSourceFolder(openedResource.getProject(), toOpenFilename))) {
          continue;
        }
        try {
          // try to get the file
          final IFile file = getFile(toOpenFilename);
          if (file != null && file.exists()) {
            // open in editor
            final IEditorPart editor = IDE.openEditor(activePage, file, false);
            Assert.isNotNull(editor);

            final ITextEditor textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
            final IDocument document = ((textEditor).getDocumentProvider()).getDocument(editor.getEditorInput());
            Assert.isNotNull(document);

            final FindReplaceDocumentAdapter frda = new FindReplaceDocumentAdapter(document);
            try {
              if (JAVA.equals(extension)) {
                IRegion region = frda.find(0, '"' + wicketId + '"', true, true, false, false);
                if (region != null) {
                  while (region != null) {
                    final IRegion li = document.getLineInformationOfOffset(region.getOffset());
                    String line = document.get(li.getOffset(), li.getLength()).trim();
                    if (line.startsWith("*") || line.startsWith("/*") || line.startsWith("//")) {
                      region = frda.find(region.getOffset() + 1, '"' + wicketId + '"', true, true, false, false);
                    } else {
                      DocumentHelper.markOccurrence(textEditor, DocumentHelper.getStringConstantName(line));
                      textEditor.selectAndReveal(region.getOffset() + 1, wicketId.length());
                      found = true;
                      break;
                    }
                  }
                } else {
                  // wicket id not found in file, so search up in tree
                  final List<Object> supertypes = TypeHelper.getSupertypes(file);
                  if (supertypes.size() > 0) {
                    if (supertypes.get(0) instanceof IFile) {
                      final IEditorPart oe = IDE.openEditor(activePage, (IFile) supertypes.get(0), false);
                      open();
                      if (!found) {
                        activePage.closeEditor(oe, false);
                      }
                    }
                  }
                }
              } else if (HTML.equals(extension)) {
                String wid_const = DocumentHelper.getNamespacePrefix(document);
                final IRegion region = frda.find(0, wid_const + ":id=\"" + wicketId, true, true, true, false);
                if (region != null) {
                  textEditor.selectAndReveal(region.getOffset() + wid_const.length() + 5, wicketId.length());
                  break;
                }
              } else if (PROPERTIES.equals(extension)) {
                // for the wicket tags that use wicket:message
                if (wicketId.startsWith("value:")) {
                  wicketId = wicketId.substring(6);
                }
                final IRegion regionBegin = frda.find(0, wicketId, true, true, false, false);
                if (regionBegin != null) {
                  IRegion sr = frda.find(regionBegin.getOffset(), "\">", true, true, false, false);
                  if (sr == null) { // properties, select till eol
                    sr = frda.find(regionBegin.getOffset(), "=", true, true, false, false);
                    if (sr == null) {
                      activePage.closeEditor(editor, false);
                      continue;
                    }
                    final IRegion lineRegion = document.getLineInformationOfOffset(sr.getOffset());
                    final int selectionLength = lineRegion.getOffset() + lineRegion.getLength() - sr.getOffset();
                    textEditor.selectAndReveal(sr.getOffset() + 1, selectionLength - 1);
                    foundInPropertiesFile = true;
                    break;
                  } else { // xml, select till </
                    final IRegion selEnd = frda.find(regionBegin.getOffset(), "</", true, true, false, false);
                    textEditor.selectAndReveal(sr.getOffset() + 2, selEnd.getOffset() - sr.getOffset() - 2);
                    foundInPropertiesFile = true;
                    break;
                  }
                } else {
                  activePage.closeEditor(editor, false);
                  continue;
                }
              }
            } catch (final BadLocationException e) {
              textEditor.resetHighlightRange();
              return;
            }
          } else {
            if (!found) {
              if (JAVA.equals(extension) && !openedResource.getName().contains("_")) {
                createJavaFile(openedResource);
              } else if (HTML.equals(extension)) {
                createHtmlFile(workbench);
              }
            }
          }
        } catch (final PartInitException pie) {
          return;
        }
      }
      if (PROPERTIES.equals(extension) && !foundInPropertiesFile) {
        if (createPropertiesFile(openedResource.getFullPath().removeFileExtension().addFileExtension(PROPERTIES).toPortableString(), wicketId + "=") != null) {
          open();
        }
      }
    }
  }

  private boolean samePackage(final String portableString, final String toOpenFilename) {
    String[] segmentsA = portableString.split("/");
    String[] segmentsB = toOpenFilename.split("/");
    if (segmentsA.length != segmentsB.length) {
      return false;
    }
    for (int i = segmentsA.length - 2; i >= 0; i--) {
      if (segmentsA[i].equals(segmentsB[i])) {
        continue;
      } else {
        return false;
      }
    }
    return true;
  }

  public List<String> getFilenamesToOpen(final IResource openedResource, final String extension) {
    Assert.isNotNull(openedResource);
    String ressourceExtension = openedResource.getFileExtension();

    final Set<String> filenames = new LinkedHashSet<String>();
    if (openJavaFileOnly) {
      filenames.add(getJavaFile(openedResource).getFullPath().toPortableString());
      return new ArrayList<String>(filenames);
    }
    if (HTML.equals(ressourceExtension)) {
      filenames.add(getJavaFile(openedResource).getFullPath().toPortableString());
      filenames.addAll(getPropertiesFilename(openedResource));
    } else if (JAVA.equals(ressourceExtension)) {
      if (!PROPERTIES.equals(extension)) {
        filenames.addAll(getHtmlFiles(openedResource));
      }
      filenames.addAll(getPropertiesFilename(openedResource));
    } else if (PROPERTIES.equals(ressourceExtension)) {
      filenames.addAll(getHtmlFiles(openedResource));
      filenames.add(getJavaFile(openedResource).getFullPath().toPortableString());
    }
    return new ArrayList<String>(filenames);
  }

  public boolean openJavaFile() {
    return JAVA.equals(extension);
  }

  public void openJavaFileOnly(final boolean openJavaFileOnly) {
    this.openJavaFileOnly = openJavaFileOnly;
  }

  public static List<String> getHtmlFiles(final IResource openedResource) {
    Assert.isNotNull(openedResource);
    final IProject project = openedResource.getProject();
    List<String> htmlFilenames = new ArrayList<String>();
    final String filename = openedResource.getFullPath().removeFileExtension().addFileExtension(HTML).toPortableString();

    final IFile file = getFile(filename);
    // is there a html file in the same folder?
    if (file != null && file.exists()) {
      htmlFilenames.add(filename);
    } else { // if not, search for one with the same name
      final FileSearcher fs = new FileSearcher(project, new Path(filename).lastSegment());
      try {
        final IJavaProject javaProject = (IJavaProject) project.getNature(JavaCore.NATURE_ID);
        final IPackageFragmentRoot[] packageFragmentRoots = javaProject.getPackageFragmentRoots();
        project.accept(fs);
        for (final IFile foundFile : fs.getFoundFiles()) {
          for (final IPackageFragmentRoot packageFragmentRoot : packageFragmentRoots) {
            if (packageFragmentRoot.getKind() == 1) { // if it's in a source folder
              if (packageFragmentRoot.getPath().segment(1).equals(foundFile.getFullPath().segment(1))) { // starting with /src
                htmlFilenames.add(foundFile.getFullPath().toPortableString());
              }
            }
          }
        }
      } catch (final CoreException e1) {
      }
    }
    FileSearcher fs = new FileSearcher(project, new Path(filename).removeFileExtension().lastSegment() + "$*");
    try {
      project.accept(fs);
      for (final IFile foundFile : fs.getFoundFiles()) {
        htmlFilenames.add(foundFile.getFullPath().toPortableString());
      }
    } catch (CoreException e) {
    }

    Collections.reverse(htmlFilenames);
    return htmlFilenames;
  }

  public static IFile getJavaFile(final IResource openedResource) {
    Assert.isNotNull(openedResource);
    String filePath = openedResource.getFullPath().removeFileExtension().addFileExtension(JAVA).toPortableString();
    String searchName = new Path(filePath).lastSegment();
    if (searchName.contains("_")) {
      searchName = searchName.split("_")[0].concat(".java");
    }
    // it is an inner class
    if (searchName.contains("$")) {
      searchName = searchName.split("\\$")[0].concat(".java");
    }
    filePath = openedResource.getFullPath().removeLastSegments(1).append(searchName).toPortableString();

    final IFile file = getFile(filePath);
    // is there a file with the same name in the same folder?
    if (file != null && file.exists()) {
      return file;
    } else { // if not, search for one with the same name, but without variations
      // String searchName = new Path(filename).lastSegment();
      // if (searchName.contains("_")) {
      // searchName = searchName.split("_")[0].concat(".java");
      // }
      // it is an inner class
      // if (searchName.contains("$")) {
      // searchName = searchName.split("\\$")[0].concat(".java");
      // }
      final FileSearcher fs = new FileSearcher(openedResource.getProject(), searchName);
      try {
        final IProject project = openedResource.getProject();
        project.accept(fs);

        if (fs.getFoundFiles().size() > 1) { // more then one file found means, there are other packages with the same filenames
          List<IPath> sourceRoots = FileSearcher.getSourceFolders(project);
          IPath orp = openedResource.getFullPath().removeLastSegments(1);
          for (IPath sourceRoot : sourceRoots) {
            if (sourceRoot.isPrefixOf(orp)) {
              for (IFile ff : fs.getFoundFiles()) {
                final IPath ffr = ff.getFullPath().removeFirstSegments(sourceRoot.segmentCount()).removeLastSegments(1);
                orp = openedResource.getFullPath().removeFirstSegments(sourceRoot.segmentCount()).removeLastSegments(1);
                if (orp.toPortableString().equals(ffr.toPortableString())) {
                  return ff;
                }
              }
            }
          }
        } else if (fs.getFoundFile() != null) {
          return fs.getFoundFile();
        }
      } catch (final CoreException e1) {
      }
    }

    return file;
  }

  /** Properties can be properties files but also xml files */
  public static List<String> getPropertiesFilename(final IResource openedResource) {
    Assert.isNotNull(openedResource);

    final List<String> propertyFiles = getWicketFile(openedResource, PROPERTIES);
    propertyFiles.add(openedResource.getParent().getFullPath() + "/wicket-package.properties");
    final List<String> xmlPropertyFiles = getWicketFile(openedResource, XML_PROPERTIES);
    propertyFiles.addAll(xmlPropertyFiles);
    final List<String> xmlFiles = getWicketFile(openedResource, XML);
    propertyFiles.addAll(xmlFiles);

    if (xmlFiles.size() == 1 || xmlPropertyFiles.size() == 1) {
      Collections.reverse(propertyFiles);
    }

    return propertyFiles;
  }

  private static List<String> getWicketFile(final IResource openedResource, final String ext) {
    Assert.isNotNull(openedResource);
    Assert.isNotNull(ext);

    final String filename = openedResource.getFullPath().removeFileExtension().addFileExtension(ext).toPortableString();
    final List<String> filenames = new ArrayList<String>();
    final IFile file = getFile(filename);

    // is there a file in the same folder, with the same name? then take this one first
    if (file != null && file.exists()) {
      filenames.add(filename);
    } else { // if not, search for one with the same name
      final FileSearcher fs = new FileSearcher(openedResource.getProject(), openedResource.getFullPath().removeFileExtension().lastSegment() + "*." + ext);
      try {
        final IProject project = openedResource.getProject();
        project.accept(fs);
        final List<IFile> ffs = fs.getFoundFiles();
        if (ffs != null) {
          for (final IFile ff : ffs) {
            filenames.add(ff.getFullPath().toPortableString());
          }
        }
      } catch (final CoreException e1) {
      }
    }
    return filenames;
  }

  private void createHtmlFile(final IWorkbench workbench) {
    /*
     * Do nothing, the html creating wizard in eclipse is not very mature final NewHTMLWizard wiz = new NewHTMLWizard(); wiz.init(workbench, new
     * StructuredSelection()); final WizardDialog dialog = new WizardDialog(workbench.getActiveWorkbenchWindow().getShell(), wiz); dialog.create();
     * dialog.open();
     */
  }

  private IFile createPropertiesFile(final String toOpenFilename, final String key) {
    final IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(toOpenFilename));
    try {
      if (!file.exists()) {
        final InputStream ins = new ByteArrayInputStream(key.getBytes());
        file.create(ins, true, null);
      } else {
        final InputStream ins = new ByteArrayInputStream(("\n" + key).getBytes());
        file.appendContents(ins, IFile.FORCE | IFile.KEEP_HISTORY, null);
      }
    } catch (final CoreException e) {
    }
    return file;
  }

  private void createJavaFile(final IResource resource) {
    Assert.isNotNull(resource);

    final OpenNewClassWizardAction action = new OpenNewClassWizardAction();
    final NewClassWizardPage ncwp = new NewClassWizardPage();

    ncwp.setTypeName(resource.getName().replaceAll("\\.html", ""), true);

    final IJavaProject javaProject = JavaCore.create(resource.getProject());
    IPackageFragmentRoot root = null;
    try {
      final IPackageFragmentRoot[] roots = javaProject.getPackageFragmentRoots();
      for (int i = 0; i < roots.length; i++) {
        if (roots[i].getKind() == IPackageFragmentRoot.K_SOURCE) {
          root = roots[i];
          break;
        }
      }

      ncwp.setPackageFragmentRoot(root, true);

    } catch (final JavaModelException e) {
    }
    final String os = root.getParent().getPath().toPortableString();
    final String fp = root.getResource().getFullPath().toPortableString().replaceFirst(os, "").substring(1);
    final String ps = resource.getProjectRelativePath().toPortableString().replaceFirst(fp, "");
    String pn = ps.replaceFirst(resource.getName(), "").substring(1).replaceAll("/", ".");
    pn = pn.substring(0, pn.length() - 1);

    ncwp.setPackageFragment(root.getPackageFragment(pn), true);

    ncwp.setSuperClass("org.apache.wicket.markup.html.WebPage", openJavaFile());

    action.setConfiguredWizardPage(ncwp);
    action.setOpenEditorOnFinish(true);
    action.run();
  }

  /** Helper to get a IFile in this workspace */
  public static IFile getFile(final String filename) {
    IFile file = null;

    if (filename != null) {
      final IPath filePath = new Path(filename);
      if ((filePath.segmentCount() > 1) && (ResourcesPlugin.getWorkspace().getRoot().getFile(filePath).exists())) {
        return ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
      }
      final IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(URIUtil.toURI(filePath.makeAbsolute()));
      for (int i = 0; (i < files.length) && (file == null); ++i) {
        if (files[i].exists()) {
          file = files[i];
          break;
        }
      }
    }

    return file;
  }

  public String getTypeLabel() {
    return null;
  }

  public String getHyperlinkText() {
    return "Open " + extension + " file and jump to " + QWickieActivator.WICKET_ID + " \"" + wicketId + "\"";
  }

  public String getURLString() {
    return this.wicketId;
  }

  @Override
  public String toString() {
    return getClass().getSimpleName() + " for " + QWickieActivator.WICKET_ID + " \"" + wicketId + "\" to " + extension + " file";
  }

}
TOP

Related Classes of qwickie.hyperlink.WicketHyperlink

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.