/*******************************************************************************
* Copyright (c) 2009, 2010 Innovation Gate GmbH.
* 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:
* Innovation Gate GmbH - initial API and implementation
******************************************************************************/
package de.innovationgate.eclipse.editors.tml;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
import org.eclipse.jface.text.rules.Token;
import de.innovationgate.eclipse.editors.helpers.WrappedRuleBasedPartionScanner;
import de.innovationgate.eclipse.editors.tmlscript.TMLScriptPartitionScanner;
public class TMLPartitionScanner extends WrappedRuleBasedPartionScanner {
private TMLRuleBasedPartitionScanner _ruleScanner = new TMLRuleBasedPartitionScanner();
private TMLScriptPartitionScanner _scriptScanner = new TMLScriptPartitionScanner();
public static final String COMMENT = "__comment";
public static final String TML_COMMENT = "__tml_comment";
public static final String TML_DISABLE = "__tml_disable";
public static final String TML_TAG_START = "__tml_tag_start";
public static final String TML_TAG_STOP = "__tml_tag_stop";
public static final String GENERIC_TAG_START = "__generic_tag_start";
public static final String GENERIC_TAG_STOP = "__generic_tag_stop";
public static final String TML_METAHEADER = "__tml_meta_header";
public static final String[] PARTITIONS = {COMMENT, TML_COMMENT, TML_TAG_START, TML_TAG_STOP, TML_DISABLE, TMLScriptPartitionScanner.TMLSCRIPT, TMLScriptPartitionScanner.MCOMMENT, TMLScriptPartitionScanner.SCOMMENT, GENERIC_TAG_START, GENERIC_TAG_STOP, TML_METAHEADER};
public TMLPartitionScanner() {
}
private List<TokenBean> insertTMLBodyPartition(List<TokenBean> tokens) {
List<TokenBean> tokenList = new ArrayList<TokenBean>();
for (int i = 0; i < tokens.size(); i++) {
TokenBean previousToken = null;
TokenBean nextToken = null;
TokenBean currentToken = tokens.get(i);
if (i > 0) {
previousToken = tokens.get(i-1);
} else {
// try to determine previous token by existing document partitioning
try {
int partOffset = currentToken.getOffset() - 1;
if (partOffset >= 0) {
ITypedRegion region = _document.getPartition(partOffset);
if (region != null) {
previousToken = new TokenBean(new Token(region.getType()), region.getLength(), region.getOffset());
}
}
} catch (BadLocationException e) {
}
}
if (i < tokens.size() - 1) {
nextToken = tokens.get(i+1);
}
if (currentToken.getToken().getData() == null && previousToken != null) {
String previousTMLTag = determineTMLTagName(previousToken, _document);
int offset = currentToken.getOffset();
int length = currentToken.getLength();
if (previousTMLTag != null && previousToken.getToken().getData().equals(TML_TAG_START) && !isTagClosed(previousToken)) {
if (nextToken != null && nextToken.getToken().getData().equals(TML_TAG_STOP)) {
String nextTMLTag = determineTMLTagName(previousToken, _document);
if (previousTMLTag.equals(nextTMLTag) &&
(previousTMLTag.equals("script") || previousTMLTag.equals("action") || previousTMLTag.equals("eventscript"))) {
List<TokenBean> subTokens = dispatchToTMLScriptScanner(offset, length);
tokenList.addAll(subTokens);
}
}
} else if (Arrays.asList(TMLScriptPartitionScanner.PARTITIONS).contains(previousToken.getToken().getData())) {
List<TokenBean> subTokens = dispatchToTMLScriptScanner(offset, length);
tokenList.addAll(subTokens);
}else {
tokenList.add(currentToken);
}
} else {
tokenList.add(currentToken);
}
}
return tokenList;
}
private List<TokenBean> dispatchToTMLScriptScanner(int offset, int length) {
if (offset >= 0 && length >= 0) {
_scriptScanner.setRange(_document, offset, length);
List<TokenBean> subTokens = _scriptScanner.computeTokens(true);
return subTokens;
} else {
return new ArrayList<TokenBean>();
}
}
private static String determineTMLTagName(TokenBean bean, IDocument document) {
if (bean == null) {
return null;
} else {
String tokenData = (String) bean.getToken().getData();
if (tokenData != null && (tokenData.equals(TML_TAG_START) || tokenData.equals(TML_TAG_STOP))) {
try {
String content = document.get(bean.getOffset(), bean.getLength());
String search = null;
if (content.startsWith("</")) {
search = "</tml:";
} else {
search = "<tml:";
}
int start = content.indexOf(search);
int stop = content.indexOf(" ");
if (stop == -1) {
stop = content.indexOf("/>");
}
if (stop == -1) {
stop = content.indexOf(">");
}
if (start != -1 && stop != -1) {
return content.substring(start + search.length(), stop);
}
} catch (BadLocationException e) {
}
}
}
return null;
}
public static String determineTMLTagName(ITypedRegion region, IDocument document) {
TokenBean bean = new TokenBean(new Token(region.getType()), region.getLength(), region.getOffset());
return determineTMLTagName(bean, document);
}
private boolean isTagClosed(TokenBean token) {
if (token != null) {
String content = null;
try {
content = _document.get(token.getOffset(), token.getLength());
} catch (BadLocationException e) {
}
if (content != null) {
return content.endsWith("/>");
}
}
return false;
}
@Override
public RuleBasedPartitionScanner getRuleScanner() {
return _ruleScanner;
}
@Override
public List<TokenBean> computeTokens() {
List<TokenBean> tokens = super.computeTokens();
tokens = insertTMLBodyPartition(tokens);
return tokens;
/*
List<TokenBean> tokensAdded = insertTMLBodyPartition(tokens);
tokens.clear();
tokens.addAll(tokensAdded);
return tokens;*/
}
}