/* * Copyright 2007 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.dom.struts.impl; import com.intellij.openapi.util.Comparing; import com.intellij.psi.ElementManipulators; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.FilePathReferenceProvider; import com.intellij.psi.xml.XmlElement; import com.intellij.psi.xml.XmlFile; import com.intellij.struts2.dom.struts.IncludeFileResolvingConverter; import com.intellij.struts2.dom.struts.model.StrutsManager; import com.intellij.struts2.dom.struts.model.StrutsModel; import com.intellij.util.xml.ConvertContext; import com.intellij.util.xml.GenericDomValue; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Set; /** * @author Gregory.Shrago * @author Yann Cébron */ public class IncludeFileResolvingConverterImpl extends IncludeFileResolvingConverter { public PsiFile fromString(@Nullable @NonNls final String value, final ConvertContext context) { if (value == null) { return null; } final XmlElement xmlElement = context.getReferenceXmlElement(); if (xmlElement == null) { return null; } final PsiReference[] references = createReferences((GenericDomValue) context.getInvocationElement(), xmlElement, context); if (references.length == 0) { return null; } final PsiElement element = references[references.length - 1].resolve(); return element instanceof PsiFile ? (PsiFile) element : null; } @NotNull public Collection<? extends PsiFile> getVariants(final ConvertContext context) { return Collections.emptyList(); } public PsiElement resolve(final PsiFile psiFile, final ConvertContext context) { // recursive self-inclusion if (context.getFile().equals(psiFile)) { return null; } return isFileAccepted(psiFile) ? super.resolve(psiFile, context) : null; } @NotNull public PsiReference[] createReferences(@NotNull final GenericDomValue genericDomValue, @NotNull final PsiElement element, @NotNull final ConvertContext context) { final String s = genericDomValue.getStringValue(); if (s == null) { return PsiReference.EMPTY_ARRAY; } final int offset = ElementManipulators.getOffsetInElement(element); return new FilePathReferenceProvider() { protected boolean isPsiElementAccepted(final PsiElement element) { return super.isPsiElementAccepted(element) && (!(element instanceof PsiFile) || isFileAccepted((PsiFile) element)); } }.getReferencesByElement(element, s, offset, true); } private static boolean isFileAccepted(@NotNull final PsiFile file) { if (file instanceof XmlFile) { final XmlFile xmlFile = (XmlFile) file; final StrutsModel model = StrutsManager.getInstance(file.getProject()).getModelByFile(xmlFile); if (model == null) { return false; } final Set<XmlFile> files = model.getConfigFiles(); return files.contains(xmlFile); } return false; } public String getErrorMessage(@Nullable final String value, final ConvertContext context) { // check if user tries to include current file if (Comparing.equal(context.getFile().getName(), value)) { return "Recursive inclusion of current file"; } // TODO check for cyclic include return "Cannot resolve file ''" + value + "'' (not included in file sets?)"; } }