Package com.intellij.struts2.reference.jsp

Source Code of com.intellij.struts2.reference.jsp.ActionLinkReferenceProvider$ActionLinkPackageReference

/*
* Copyright 2013 The authors
* Licensed 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 com.intellij.struts2.reference.jsp;

import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.javaee.web.CustomServletReferenceAdapter;
import com.intellij.javaee.web.ServletMappingInfo;
import com.intellij.openapi.paths.PathReference;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceBase;
import com.intellij.struts2.StrutsIcons;
import com.intellij.struts2.dom.struts.action.Action;
import com.intellij.struts2.dom.struts.model.StrutsManager;
import com.intellij.struts2.dom.struts.model.StrutsModel;
import com.intellij.struts2.dom.struts.strutspackage.StrutsPackage;
import com.intellij.struts2.model.constant.StrutsConstantHelper;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ConstantFunction;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import icons.Struts2Icons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

/**
* Provides links to Action-URLs in all places where Servlet-URLs are processed.
*
* @author Yann Cébron
*/
public class ActionLinkReferenceProvider extends CustomServletReferenceAdapter {

  protected PsiReference[] createReferences(@NotNull final PsiElement psiElement,
                                            final int offset,
                                            final String text,
                                            @Nullable final ServletMappingInfo info,
                                            final boolean soft) {
    final StrutsModel strutsModel = StrutsManager.getInstance(psiElement.getProject()).getCombinedModel(psiElement);

    if (strutsModel == null) {
      return PsiReference.EMPTY_ARRAY;
    }

    final List<String> actionExtensions = StrutsConstantHelper.getActionExtensions(psiElement);
    if (actionExtensions.isEmpty()) {
      return PsiReference.EMPTY_ARRAY;
    }

    if (StringUtil.indexOf(text, '/') != -1) {
      return new PsiReference[]{
        new ActionLinkPackageReference(psiElement, offset, text, soft, strutsModel),
        new ActionLinkReference(psiElement, offset, text, soft, strutsModel, actionExtensions)
      };
    }
    else {
      return new PsiReference[]{
        new ActionLinkReference(psiElement, offset, text, soft, strutsModel, actionExtensions)
      };
    }
  }

  @Nullable
  public PathReference createWebPath(final String path,
                                     @NotNull final PsiElement psiElement,
                                     final ServletMappingInfo servletMappingInfo) {
    final StrutsManager strutsManager = StrutsManager.getInstance(psiElement.getProject());
    if (strutsManager.getCombinedModel(psiElement) == null) {
      return null;
    }

    return new PathReference(path, new ConstantFunction<PathReference, Icon>(Struts2Icons.Action)); /*{
TODO not needed so far ?!
   public PsiElement resolve() {
        return action.getXmlTag();
      }
    };*/
  }


  private static class ActionLinkReference extends PsiReferenceBase<PsiElement> implements EmptyResolveMessageProvider {

    private final StrutsModel strutsModel;
    private final List<String> actionExtensions;
    private final String fullActionPath;

    private ActionLinkReference(final PsiElement element,
                                final int offset,
                                final String text,
                                final boolean soft,
                                final StrutsModel strutsModel,
                                final List<String> actionExtensions) {
      super(element, new TextRange(offset, offset + text.length()), soft);
      this.strutsModel = strutsModel;
      this.actionExtensions = actionExtensions;

      fullActionPath = PathReference.trimPath(getValue());
      final int lastSlash = fullActionPath.lastIndexOf("/");

      // adapt TextRange to everything behind /packageName/
      if (lastSlash != -1) {
        setRangeInElement(TextRange.from(offset + lastSlash + 1, fullActionPath.length() - lastSlash - 1));
      }

      // reduce to action-name if full path given
      for (final String actionExtension : actionExtensions) {
        if (StringUtil.endsWith(fullActionPath, actionExtension)) {
          setRangeInElement(TextRange.from(getRangeInElement().getStartOffset(),
                                           getRangeInElement().getLength() - actionExtension.length()));
          break;
        }
      }
    }

    public PsiElement resolve() {
      final String ourActionExtension = ContainerUtil.find(actionExtensions, new Condition<String>() {
        public boolean value(final String s) {
          return StringUtil.endsWith(fullActionPath, s);
        }
      });
      if (ourActionExtension == null) {
        return null;
      }

      final String actionName = getActionName(fullActionPath, ourActionExtension);
      final String namespace = getNamespace(fullActionPath);
      final List<Action> actions = strutsModel.findActionsByName(actionName, namespace);
      if (actions.isEmpty()) {
        return null;
      }

      final Action myAction = actions.get(0);
      return myAction.getXmlTag();
    }

    @NotNull
    public Object[] getVariants() {
      final String namespace = getNamespace(fullActionPath);

      final String firstExtension = actionExtensions.get(0);

      final List<Action> actionList = strutsModel.getActionsForNamespace(namespace);
      final List<Object> variants = new ArrayList<Object>(actionList.size());
      for (final Action action : actionList) {
        final String actionPath = action.getName().getStringValue();
        if (actionPath != null) {
          variants.add(LookupElementBuilder.create(actionPath + firstExtension)
                         .withIcon(Struts2Icons.Action)
                         .withTypeText(action.getNamespace()));
        }
      }
      return ArrayUtil.toObjectArray(variants);
    }

    @NotNull
    public String getUnresolvedMessagePattern() {
      return "Cannot resolve action '" + getValue() + "'";
    }

    @NotNull
    private static String getActionName(final String fullActionPath,
                                        final String ourActionExtension) {
      final int slashIndex = fullActionPath.lastIndexOf("/");
      final int extensionIndex = fullActionPath.lastIndexOf(ourActionExtension);
      return fullActionPath.substring(slashIndex + 1, extensionIndex);
    }
  }

  /**
   * Extracts the namespace from the given action path.
   *
   * @param fullActionPath Full path.
   * @return Namespace.
   */
  @NotNull
  private static String getNamespace(final String fullActionPath) {

    final int lastSlash = fullActionPath.lastIndexOf('/');
    // no slash, use fake "root" for resolving "myAction.action"
    if (lastSlash == -1) {
      return "/";
    }

    // root-package
    if (lastSlash == 0) {
      return "/";
    }

    final int firstSlash = fullActionPath.indexOf('/');
    return fullActionPath.substring(firstSlash, lastSlash);
  }


  /**
   * Provides reference to S2-package within action-path.
   */
  private static class ActionLinkPackageReference extends PsiReferenceBase<PsiElement> implements EmptyResolveMessageProvider {

    private final String namespace;
    private final List<StrutsPackage> allStrutsPackages;
    private final String fullActionPath;

    private ActionLinkPackageReference(final PsiElement element,
                                       final int offset,
                                       final String text,
                                       final boolean soft,
                                       final StrutsModel strutsModel) {
      super(element, computeRange(offset, text), soft);

      fullActionPath = PathReference.trimPath(text);
      namespace = getNamespace(fullActionPath);

      allStrutsPackages = strutsModel.getStrutsPackages();
    }

    private static TextRange computeRange(final int offset, final String text) {
      final int lastSlash = text.lastIndexOf('/');
      return new TextRange(offset, offset + (lastSlash == -1 ? text.length() : lastSlash));
    }

    public PsiElement resolve() {
      for (final StrutsPackage strutsPackage : allStrutsPackages) {
        if (Comparing.equal(namespace, strutsPackage.searchNamespace())) {
          return strutsPackage.getXmlTag();
        }
      }

      return null;
    }

    @NotNull
    public Object[] getVariants() {
      return ContainerUtil.map2Array(allStrutsPackages, Object.class, new Function<StrutsPackage, Object>() {
        public Object fun(final StrutsPackage strutsPackage) {
          final String packageNamespace = strutsPackage.searchNamespace();
          return LookupElementBuilder.create(packageNamespace.length() != 1 ? packageNamespace + "/" : packageNamespace)
            .withIcon(StrutsIcons.STRUTS_PACKAGE)
            .withTypeText(strutsPackage.getName().getStringValue());
        }
      });
    }

    @NotNull
    public String getUnresolvedMessagePattern() {
      return "Cannot resolve Struts 2 package '" + namespace + "'";
    }
  }
}
TOP

Related Classes of com.intellij.struts2.reference.jsp.ActionLinkReferenceProvider$ActionLinkPackageReference

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.