blob: 86f3f0ce0820c44a8c94251571b2456f858c39b7 [file] [log] [blame]
/*
* Copyright 2002-2007 Sascha Weinreuter
*
* 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 org.intellij.lang.xpath.xslt.intentions;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlChildRole;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import org.intellij.lang.xpath.xslt.XsltSupport;
import org.intellij.lang.xpath.xslt.util.XsltCodeInsightUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 20.06.2007
*/
public class ReplaceWithXslAttribute implements IntentionAction {
@NotNull
public String getText() {
return "Replace with 'xsl:attribute'";
}
@NotNull
public String getFamilyName() {
return "Replace with xsl:attribute";
}
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
if (!XsltSupport.isXsltFile(file)) return false;
final int offset = editor.getCaretModel().getOffset();
final PsiElement element = file.findElementAt(offset);
final XmlAttribute attr = PsiTreeUtil.getParentOfType(element, XmlAttribute.class, false);
if (attr == null || attr.getValueElement() == null) {
return false;
}
if (XsltSupport.isXsltTag(attr.getParent())) {
return false;
}
final ASTNode node = attr.getNode();
if (node == null) return false;
final ASTNode nameNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
if (nameNode == null) {
return false;
} else {
return nameNode.getTextRange().contains(offset);
}
}
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final int offset = editor.getCaretModel().getOffset();
final PsiElement element = file.findElementAt(offset);
final XmlAttribute attr = PsiTreeUtil.getParentOfType(element, XmlAttribute.class, false);
assert attr != null;
final XmlAttributeValue valueElement = attr.getValueElement();
assert valueElement != null;
final String s = attr.getValueTextRange().substring(valueElement.getText());
final List<Pair<String, Boolean>> chunks = new ArrayList<Pair<String, Boolean>>();
final StringBuilder builder = new StringBuilder(s.length());
final PsiFile[] files = XsltSupport.getFiles(attr);
int i=0, j=0;
while (i < s.length()) {
final char c = s.charAt(i++);
if (c == '{' && j < files.length) {
if (i < s.length() - 1 && s.charAt(i) != '{') {
final PsiFile f = files[j++];
if (builder.length() > 0) {
chunks.add(Pair.create(builder.toString(), Boolean.FALSE));
builder.setLength(0);
}
chunks.add(Pair.create(f.getText(), Boolean.TRUE));
i += f.getTextLength();
if (s.charAt(i) == '}') i++;
} else {
builder.append(c);
i++;
}
} else {
builder.append(c);
}
}
if (builder.length() > 0) {
chunks.add(Pair.create(builder.toString(), Boolean.FALSE));
}
final XmlTag parent = attr.getParent();
final XmlTag attrTag = parent.createChildTag("attribute", XsltSupport.XSLT_NS, null, false);
attrTag.setAttribute("name", attr.getName()); // local name?
final String value = attr.getNamespace();
if (value.length() > 0) {
attrTag.setAttribute("namespace", value);
}
for (Pair<String, Boolean> chunk : chunks) {
final XmlTag child;
if (chunk.second) {
child = parent.createChildTag("value-of", XsltSupport.XSLT_NS, null, false);
child.setAttribute("select", chunk.first);
// } else if (chunks.size() == 1) {
// TODO: really? or always create an xsl:text?
// attrTag.add(attrTag.getManager().getElementFactory().createDisplayText(chunk.first));
// continue;
} else {
child = parent.createChildTag("text", XsltSupport.XSLT_NS, null, false);
child.add(XmlElementFactory.getInstance(child.getProject()).createDisplayText(chunk.first));
}
attrTag.add(child);
}
final PsiElement child = XsltCodeInsightUtil.findFirstRealTagChild(parent);
if (child != null) {
parent.addBefore(attrTag, child);
} else {
parent.add(attrTag);
}
attr.delete();
}
public boolean startInWriteAction() {
return true;
}
}