/*
 * Copyright 2000-2014 JetBrains s.r.o.
 *
 * 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.psi.impl.source.resolve.reference.impl.manipulators;

import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.AbstractElementManipulator;
import com.intellij.psi.PsiElement;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlTokenType;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;

/**
 * Created by IntelliJ IDEA.
 * User: ik
 * Date: 06.01.2004
 * Time: 20:00:23
 * To change this template use Options | File Templates.
 */
public class XmlAttributeValueManipulator extends AbstractElementManipulator<XmlAttributeValue> {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.resolve.reference.impl.manipulators.XmlAttributeValueManipulator");

  @Override
  public XmlAttributeValue handleContentChange(@NotNull XmlAttributeValue element, @NotNull TextRange range, String newContent) throws IncorrectOperationException {
    CheckUtil.checkWritable(element);

    String text;
    final String oldText = element.getText();
    try {
      String textBeforeRange = oldText.substring(0, range.getStartOffset());
      String textAfterRange = oldText.substring(range.getEndOffset(), oldText.length());
      newContent = oldText.startsWith("'") || oldText.endsWith("'") ?
                   newContent.replace("'", oldText.contains("&#39;") ? "&#39;" : "&apos;") :
                   newContent.replace("\"", oldText.contains("&#34;") ? "&#34;" : "&quot;");
      text = "<a value=" + textBeforeRange + newContent + textAfterRange + "/>";
    } catch(StringIndexOutOfBoundsException e) {
      LOG.error("Range: " + range + " in text: '" + oldText + "'", e);
      throw e;
    }
    final XmlTag tag = XmlElementFactory.getInstance(element.getProject()).createTagFromText(text);
    final XmlAttribute attribute = tag.getAttribute("value");
    assert attribute != null && attribute.getValueElement() != null;
    return (XmlAttributeValue)element.replace(attribute.getValueElement());
  }

  @Override
  @NotNull
  public TextRange getRangeInElement(@NotNull final XmlAttributeValue xmlAttributeValue) {
    final PsiElement first = xmlAttributeValue.getFirstChild();
    if (first == null) {
      return TextRange.EMPTY_RANGE;
    }
    final ASTNode firstNode = first.getNode();
    assert firstNode != null;
    final PsiElement last = xmlAttributeValue.getLastChild();
    final ASTNode lastNode = last != null && last != first ? last.getNode() : null;

    final int textLength = xmlAttributeValue.getTextLength();
    final int start = firstNode.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_START_DELIMITER ? first.getTextLength() : 0;
    final int end = lastNode != null && lastNode.getElementType() == XmlTokenType.XML_ATTRIBUTE_VALUE_END_DELIMITER ? last.getTextLength() : 0;
    return new TextRange(start, textLength - end);
  }
}

@@ -2413,15 +2413,8 @@
 ange
- + %22/%3E%22
 ;%0A  
@@ -2791,78 +2791,115 @@
     
-return (XmlAttributeValue)element.replace(attribute.getValueElement())
+element.getNode().replaceAllChildrenToChildrenOf(attribute.getValueElement().getNode());%0A    return element
 ;%0A  

replace value content only to keep jsp happy don't close the tag for cases with unclosed attributes