blob: c458e5ca85551ba12743c7592658998f0d1f6166 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.css.core.internal.document;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import org.eclipse.wst.css.core.internal.provisional.document.ICSSNode;
import org.eclipse.wst.css.core.internal.util.CSSUtil;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegionList;
/**
*
*/
class CSSModelDeletionContext {
private int fOldStart = -1;
private int fOldLength = 0;
private int fNewStart = -1;
private int fNewLength = 0;
private int fLengthDifference = 0;
private IStructuredDocumentRegionList fOldStructuredDocumentRegions = null;
// private ICSSNode fRootNode = null;
private int fRemovedRangeBegin = -1;
private int fRemovedRangeEnd = -1;
private CSSNodeListImpl fNodesToBeRemoved = new CSSNodeListImpl();
/**
* CSSModelDeletionContext constructor comment.
*/
CSSModelDeletionContext(ICSSNode rootNode) {
super();
// fRootNode = rootNode;
}
/**
*
*/
boolean addNodeToBeRemoved(ICSSNode node) {
int nNodes = fNodesToBeRemoved.getLength();
for (int i = 0; i < nNodes; i++) {
ICSSNode parent = fNodesToBeRemoved.item(i);
if (CSSModelUtil.isParentOf(parent, node)) {
return false;
}
}
fNodesToBeRemoved.appendNode(node);
return true;
}
/**
*
*/
void expandRemovedRangeBegin(IStructuredDocumentRegion flatNode) {
if (flatNode == null) {
return;
}
int newBegin = flatNode.getStart(); // fOldStart == fNewStart, right??
if (fRemovedRangeBegin < 0 || newBegin < fRemovedRangeBegin) {
fRemovedRangeBegin = newBegin;
}
}
/**
*
*/
void expandRemovedRangeEnd(IStructuredDocumentRegion flatNode) {
if (flatNode == null) {
return;
}
int newEnd = flatNode.getEnd() + ((isOldNode(flatNode)) ? fLengthDifference : 0);
if (fRemovedRangeEnd < 0 || fRemovedRangeEnd < newEnd) {
fRemovedRangeEnd = newEnd;
}
}
/**
*
*/
private CSSStructuredDocumentRegionContainer findContainer(CSSNodeImpl parent, IStructuredDocumentRegion flatNode) {
if (parent instanceof CSSStructuredDocumentRegionContainer) {
// Am i a container of flatNode?
IStructuredDocumentRegion firstNode = ((CSSStructuredDocumentRegionContainer) parent).getFirstStructuredDocumentRegion();
IStructuredDocumentRegion lastNode = ((CSSStructuredDocumentRegionContainer) parent).getLastStructuredDocumentRegion();
int firstStart = getOriginalOffset(firstNode);
int lastStart = getOriginalOffset(lastNode);
int start = flatNode.getStart();
if (firstStart <= start && start <= lastStart) {
// I am a container, is my child a container ?
for (ICSSNode node = parent.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node instanceof CSSNodeImpl) {
CSSStructuredDocumentRegionContainer container = findContainer((CSSNodeImpl) node, flatNode);
if (container != null) {
return container;
}
}
}
return (CSSStructuredDocumentRegionContainer) parent;
}
}
return null;
}
/**
*
*/
CSSStructuredDocumentRegionContainer findDeletionTarget(CSSNodeImpl parent, IStructuredDocumentRegion flatNode) {
CSSStructuredDocumentRegionContainer target = findContainer(parent, flatNode);
if (target == null) {
return null;
}
// System.out.print(flatNode.toString() + ": ");
// child a(=====)b(=====)c
// parent (================) a,c can remove parent, but b cannot.
ICSSNode child;
for (child = target.getFirstChild(); child != null && !(child instanceof CSSStructuredDocumentRegionContainer); child = child.getNextSibling()) {
// just advancing
}
if (child == null) {
// System.out.println("target has no children."); // TESTBYCOZY
return target; // has no child containers.
}
else {
IStructuredDocumentRegion firstNode = ((CSSStructuredDocumentRegionContainer) child).getFirstStructuredDocumentRegion();
if (flatNode.getStart() < getOriginalOffset(firstNode)) {
// System.out.println("flatNode is in front of first child");
// // TESTBYCOZY
return target; // a
}
}
for (child = target.getLastChild(); child != null && !(child instanceof CSSStructuredDocumentRegionContainer); child = child.getPreviousSibling()) {
// just advancing
}
if (child == null) {
// System.out.println("target has no children."); // TESTBYCOZY
return target; // has no child containers.
}
else {
IStructuredDocumentRegion firstNode = ((CSSStructuredDocumentRegionContainer) child).getFirstStructuredDocumentRegion();
if (getOriginalOffset(firstNode) < flatNode.getStart()) {
// System.out.println("flatNode is in after of last child");
// // TESTBYCOZY
return target; // c
}
}
// System.out.println("flatNode inner of children"); // TESTBYCOZY
return null; // b
}
/**
*
*/
Iterator getNodesToBeRemoved() {
Collection nodes = new ArrayList();
int nNodes = fNodesToBeRemoved.getLength();
for (int i = 0; i < nNodes; i++) {
nodes.add(fNodesToBeRemoved.item(i));
}
return nodes.iterator();
}
/**
*
*/
private int getOriginalOffset(IStructuredDocumentRegion flatNode) {
int offset = 0;
if (flatNode != null) {
offset = flatNode.getStart();
if (0 <= fLengthDifference) {
if (fNewStart + fNewLength < offset) {
offset -= fLengthDifference;
}
}
else {
if (fOldStart + fOldLength <= offset || (fNewStart < 0 && fOldStart <= offset && !isOldNode(flatNode)) || (0 <= fNewStart && fNewStart + fNewLength <= offset && !isOldNode(flatNode))) {
offset -= fLengthDifference;
}
}
}
return offset;
}
/**
*
*/
int getRemovedRangeBegin() {
return fRemovedRangeBegin;
}
/**
*
*/
int getRemovedRangeEnd() {
return fRemovedRangeEnd;
}
/**
*
*/
private boolean isOldNode(IStructuredDocumentRegion flatNode) {
if (fOldStructuredDocumentRegions != null) {
for (Enumeration e = fOldStructuredDocumentRegions.elements(); e.hasMoreElements();) {
if (e.nextElement() == flatNode) {
return true;
}
}
}
return false;
}
/**
*
*/
void setupContext(IStructuredDocumentRegionList newStructuredDocumentRegions, IStructuredDocumentRegionList oldStructuredDocumentRegions) {
IStructuredDocumentRegion flatNode = null;
fOldLength = CSSUtil.getTextLength(oldStructuredDocumentRegions);
if (oldStructuredDocumentRegions != null && 0 < oldStructuredDocumentRegions.getLength() && (flatNode = oldStructuredDocumentRegions.item(0)) != null) {
fOldStart = flatNode.getStart();
}
else {
fOldStart = -1;
}
fNewLength = CSSUtil.getTextLength(newStructuredDocumentRegions);
if (newStructuredDocumentRegions != null && 0 < newStructuredDocumentRegions.getLength() && (flatNode = newStructuredDocumentRegions.item(0)) != null) {
fNewStart = flatNode.getStart();
fRemovedRangeBegin = fNewStart;
fRemovedRangeEnd = fNewStart + fNewLength;
}
else {
fNewStart = -1;
fRemovedRangeBegin = fRemovedRangeEnd = -1;
}
fLengthDifference = fNewLength - fOldLength;
fOldStructuredDocumentRegions = oldStructuredDocumentRegions;
// cleanup nodes
while (0 < fNodesToBeRemoved.getLength()) {
fNodesToBeRemoved.removeNode(0);
}
}
}