blob: e0244fcc2fdda0c9e72e1269666ab04c40add77a [file] [log] [blame]
/*
* Copyright 2008 Google Inc.
*
* 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.google.gwt.resources.css.ast;
import java.util.List;
/**
* A visitor that can make structural modifications to a CSS tree.
*/
@SuppressWarnings("unchecked")
public class CssModVisitor extends CssVisitor {
private class ListContext<T extends CssNode> implements Context {
private int index;
private List list;
private boolean removed;
private boolean replaced;
public boolean canInsert() {
return true;
}
public boolean canRemove() {
return true;
}
public void insertAfter(CssNode node) {
checkRemoved();
list.add(index + 1, node);
didChange = true;
}
public void insertBefore(CssNode node) {
checkRemoved();
list.add(index++, node);
didChange = true;
}
public void removeMe() {
checkState();
list.remove(index--);
didChange = removed = true;
}
public void replaceMe(CssNode node) {
checkState();
checkReplacement((CssNode) list.get(index), node);
list.set(index, node);
didChange = replaced = true;
}
protected void traverse(List<? extends CssNode> list) {
this.list = list;
for (index = 0; index < list.size(); ++index) {
removed = replaced = false;
doTraverse(list.get(index), this);
}
}
private void checkRemoved() {
if (removed) {
throw new CssCompilerException("Node was already removed");
}
}
private void checkState() {
checkRemoved();
if (replaced) {
throw new CssCompilerException("Node was already replaced");
}
}
}
protected static void checkReplacement(CssNode origNode, CssNode newNode) {
if (newNode == null) {
throw new CssCompilerException("Cannot replace with null");
}
if (newNode == origNode) {
throw new CssCompilerException(
"The replacement is the same as the original");
}
}
private boolean didChange;
public boolean didChange() {
return didChange;
}
@Override
protected void doAcceptWithInsertRemove(List<? extends CssNode> list) {
ListContext context = new ListContext();
context.traverse(list);
}
}