/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.flex.compiler.internal.mxml; import static org.apache.flex.compiler.constants.IMXMLCoreConstants.*; import java.util.Collection; import org.apache.flex.compiler.common.ISourceLocation; import org.apache.flex.compiler.internal.parsing.ISourceFragment; import org.apache.flex.compiler.internal.parsing.SourceFragment; import org.apache.flex.compiler.internal.parsing.mxml.MXMLToken; import org.apache.flex.compiler.mxml.IMXMLTextData; import org.apache.flex.compiler.parsing.MXMLTokenTypes; import org.apache.flex.compiler.problems.ICompilerProblem; /** * Encapsulation of a block of text in MXML */ public class MXMLTextData extends MXMLUnitData implements IMXMLTextData { /** * Constructor. */ public MXMLTextData(MXMLToken textToken) { text = textToken.getText(); setOffsets(textToken.getStart(), textToken.getEnd()); setLine(textToken.getLine()); setColumn(textToken.getColumn()); setEndLine(textToken.getEndLine()); setEndColumn(textToken.getEndColumn()); switch (textToken.getType()) { case MXMLTokenTypes.TOKEN_TEXT: { type = TextType.TEXT; break; } case MXMLTokenTypes.TOKEN_WHITESPACE: { type = TextType.WHITESPACE; break; } case MXMLTokenTypes.TOKEN_CDATA: { type = TextType.CDATA; break; } case MXMLTokenTypes.TOKEN_COMMENT: { type = TextType.COMMENT; break; } case MXMLTokenTypes.TOKEN_ASDOC_COMMENT: { type = TextType.ASDOC; break; } } } /** * The represented text */ private String text; private TextType type; // // Object overrides // // For debugging only. This format is nice in the Eclipse debugger. @Override public String toString() { StringBuilder sb = new StringBuilder(); // Display TEXT, WHITESPACE, etc. sb.append(getTextType()); sb.append(' '); // Display the text characters. sb.append('"'); sb.append(getEscapedContent()); sb.append('"'); sb.append(' '); // Display line, column, start, and end as "17:5 160-188". sb.append(super.toString()); return sb.toString(); } // // MXMLUnitData overrides // @Override public boolean isText() { return true; } // For debugging only. @Override public String getTypeString() { StringBuilder sb = new StringBuilder(); sb.append(super.getTypeString()); sb.append(":"); sb.append(getTextType()); return sb.toString(); } // For debugging only. This format is nice in a text file. @Override public String toDumpString() { StringBuilder sb = new StringBuilder(); sb.append(super.toDumpString()); sb.append('\t'); sb.append('|'); sb.append(getEscapedContent()); sb.append('|'); return sb.toString(); } // // IMXMLTextData implementations // @Override public String getContent() { return text; } @Override public TextType getTextType() { return type; } // // Other methods // // For debugging only. private String getEscapedContent() { String s = getContent(); s = s.replaceAll("\n", "\\\\n"); s = s.replaceAll("\r", "\\\\r"); s = s.replaceAll("\t", "\\\\t"); return s; } @Override public String getCompilableText() { switch (type) { case TEXT: case CDATA: case WHITESPACE: { return getContents(); } case ASDOC: case COMMENT: { return ""; } } assert false; return null; } @Override public int getCompilableTextStart() { return getContentsStart(); } @Override public int getCompilableTextEnd() { return getContentsEnd(); } @Override public int getCompilableTextLine() { return getLine(); } @Override public int getCompilableTextColumn() { return (getContentsStart() - getAbsoluteStart()) + getColumn(); } /** * Return the text contained within this unit, without any opening or * closing delimiters * * @return a normalized string */ public String getContents() { String tokenString = text; switch (type) { case CDATA: { if (tokenString.endsWith(cDataEnd)) { tokenString = tokenString.substring(cDataStart.length(), tokenString.length() - cDataEnd.length()); } else { tokenString = tokenString.substring(cDataStart.length()); } return tokenString; } case ASDOC: { if (tokenString.endsWith(asDocEnd)) { tokenString = tokenString.substring(asDocStart.length(), tokenString.length() - asDocEnd.length()); } else { tokenString = tokenString.substring(asDocStart.length()); } return tokenString; } case COMMENT: { if (tokenString.endsWith(commentEnd)) { tokenString = tokenString.substring(commentStart.length(), tokenString.length() - commentEnd.length()); } else { tokenString = tokenString.substring(commentStart.length()); } return tokenString; } default: { break; } } return text; } /** * @return The start offset of actual content */ public int getContentsStart() { switch (type) { case CDATA: return getAbsoluteStart() + cDataStart.length(); case ASDOC: return getAbsoluteStart() + asDocStart.length(); case COMMENT: return getAbsoluteStart() + commentStart.length(); } return getAbsoluteStart(); } /** * @return The end offset of content */ public int getContentsEnd() { switch (type) { case CDATA: return text.endsWith(cDataEnd) ? getAbsoluteEnd() - cDataEnd.length() : getAbsoluteEnd(); case ASDOC: return text.endsWith(asDocEnd) ? getAbsoluteEnd() - asDocEnd.length() : getAbsoluteEnd(); case COMMENT: return text.endsWith(commentEnd) ? getAbsoluteEnd() - commentEnd.length() : getAbsoluteEnd(); } return getAbsoluteEnd(); } public int getContentsLine() { return getLine(); } public int getContentsColumn() { switch (type) { case CDATA: return getColumn() + cDataStart.length(); case ASDOC: return getColumn() + asDocStart.length(); case COMMENT: return getColumn() + commentStart.length(); } return getColumn(); } @Override public ISourceFragment[] getFragments(Collection<ICompilerProblem> problems) { ISourceLocation location = this; switch (type) { case TEXT: { // TEXT might contain one or more entities, // in which case we will return multiple fragments. MXMLDialect mxmlDialect = getMXMLDialect(); return EntityProcessor.parse(text, location, mxmlDialect, problems); } case WHITESPACE: { // WHITESPACE creates only a single fragment. ISourceFragment fragment = new SourceFragment(text, location); return new ISourceFragment[] {fragment}; } case CDATA: { // CDATA creates only a single fragment. ISourceFragment fragment = new SourceFragment(text, getContents(), getContentsStart(), getContentsLine(), getContentsColumn()); return new ISourceFragment[] {fragment}; } default: { assert false : "Unexpected type of MXMLTextData"; } } return null; } }