/*
* ModifierUtils.java
*
* Copyright (c) 2006 David Holroyd
*
* 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 uk.co.badgersinfoil.metaas.impl;
import java.util.HashMap;
import java.util.Map;
import org.asdt.core.internal.antlr.AS3Parser;
import uk.co.badgersinfoil.metaas.dom.Visibility;
import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListToken;
import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
/**
* Helpers for dealing with the modifiers list.
*/
class ModifierUtils {
private static class ModInfo {
public int tokenType;
public Visibility vis;
public String keyword;
public ModInfo(int tokenType, Visibility vis, String keyword) {
this.tokenType = tokenType;
this.vis = vis;
this.keyword = keyword;
}
}
private static Map modinfoByTokenType = new HashMap();
private static Map modinfoByVisibility = new HashMap();
static {
mapMod(AS3Parser.PRIVATE, Visibility.PRIVATE, "private");
mapMod(AS3Parser.PUBLIC, Visibility.PUBLIC, "public");
mapMod(AS3Parser.PROTECTED, Visibility.PROTECTED, "protected");
mapMod(AS3Parser.INTERNAL, Visibility.INTERNAL, "internal");
mapMod(Integer.MIN_VALUE, Visibility.DEFAULT, null);
}
private static void mapMod(int tokenType, Visibility vis, String keyword) {
ModInfo inf = new ModInfo(tokenType, vis, keyword);
modinfoByTokenType.put(new Integer(tokenType), inf);
modinfoByVisibility.put(vis, inf);
}
private static ModInfo getModInfo(int tokenType) {
return (ModInfo)modinfoByTokenType.get(new Integer(tokenType));
}
private static ModInfo getModInfo(Visibility vis) {
ModInfo result = (ModInfo)modinfoByVisibility.get(vis);
if (result == null) {
throw new IllegalArgumentException("unknown kind of visibility: "+vis);
}
return result;
}
public static Visibility getVisibility(LinkedListTree modifiers) {
for (ASTIterator i=new ASTIterator(modifiers); i.hasNext(); ) {
LinkedListTree mod = i.next();
ModInfo modInfo = getModInfo(mod.getType());
if (modInfo != null) {
return modInfo.vis;
}
}
return Visibility.DEFAULT;
}
private static boolean hasModifierFlag(LinkedListTree modifiers, int type) {
for (ASTIterator i=new ASTIterator(modifiers); i.hasNext(); ) {
LinkedListTree mod = i.next();
if (mod.getType() == type) {
return true;
}
}
return false;
}
public static boolean isDynamic(LinkedListTree modifiers) {
return hasModifierFlag(modifiers, AS3Parser.DYNAMIC);
}
public static boolean isOverride(LinkedListTree modifiers) {
return hasModifierFlag(modifiers, AS3Parser.OVERRIDE);
}
public static boolean isFinal(LinkedListTree modifiers) {
return hasModifierFlag(modifiers, AS3Parser.FINAL);
}
public static void setDynamic(LinkedListTree modifiers, boolean value) {
setModifierFlag(modifiers, value, AS3Parser.DYNAMIC, "dynamic");
}
public static void setOverride(LinkedListTree modifiers, boolean value) {
setModifierFlag(modifiers, value, AS3Parser.OVERRIDE, "override");
}
public static void setFinal(LinkedListTree modifiers, boolean value) {
setModifierFlag(modifiers, value, AS3Parser.FINAL, "final");
}
private static void setModifierFlag(LinkedListTree modifiers, boolean flag, int type, String text) {
for (ASTIterator i=new ASTIterator(modifiers); i.hasNext(); ) {
LinkedListTree mod = i.next();
if (mod.getType() == type) {
if (flag) return;
else {
i.remove();
if (modifiers.getChildCount() == 0) {
deleteAllChildTokens(modifiers);
}
}
return;
}
}
if (flag) {
LinkedListTree node = ASTUtils.newAST(type, text);
node.appendToken(TokenBuilder.newSpace());
modifiers.addChildWithTokens(node);
}
}
public static void setVisibility(LinkedListTree modifiers, Visibility protection) {
ModInfo modInfo = getModInfo(protection);
for (ASTIterator i=new ASTIterator(modifiers); i.hasNext(); ) {
LinkedListTree mod = i.next();
if (isVisibilityKeyword(mod)) {
if (modInfo.keyword == null) {
i.remove();
if (modifiers.getChildCount() == 0) {
deleteAllChildTokens(modifiers);
}
} else {
mod.token.setType(modInfo.tokenType);
mod.token.setText(modInfo.keyword);
}
return;
}
}
LinkedListTree mod = ASTUtils.newAST(modInfo.tokenType, modInfo.keyword);
mod.appendToken(TokenBuilder.newSpace());
modifiers.addChildWithTokens(mod);
}
private static boolean isVisibilityKeyword(LinkedListTree mod) {
return getModInfo(mod.getType()) != null;
}
private static void deleteAllChildTokens(LinkedListTree modifiers) {
for (LinkedListToken tok=modifiers.getStartToken(); tok!=null && tok!=modifiers.getStopToken(); ) {
LinkedListToken next = tok.getNext();
tok.delete();
tok = next;
}
modifiers.setStartToken(null);
modifiers.setStopToken(null);
}
/**
* Constructs a new MODIFIERS node which represents the given
* visibility as an AST containing either "public", "private",
* "protected", "internal" or no children (i.e. default visibility).
*/
public static LinkedListTree toModifiers(Visibility visibility) {
if (Visibility.DEFAULT.equals(visibility)) {
return ASTUtils.newPlaceholderAST(AS3Parser.MODIFIERS);
}
LinkedListTree modifiers = ASTUtils.newImaginaryAST(AS3Parser.MODIFIERS);
ModInfo modInfo = getModInfo(visibility);
LinkedListTree mod = ASTUtils.newAST(modInfo.tokenType, modInfo.keyword);
mod.appendToken(TokenBuilder.newSpace());
modifiers.addChildWithTokens(mod);
return modifiers;
}
}