/* * * 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.codegen.mxml; import java.io.FilterWriter; import org.apache.flex.compiler.codegen.mxml.IMXMLEmitter; import org.apache.flex.compiler.definitions.IClassDefinition; import org.apache.flex.compiler.internal.codegen.Emitter; import org.apache.flex.compiler.internal.codegen.as.ASEmitterTokens; import org.apache.flex.compiler.projects.ICompilerProject; import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.tree.mxml.IMXMLArrayNode; import org.apache.flex.compiler.tree.mxml.IMXMLBooleanNode; import org.apache.flex.compiler.tree.mxml.IMXMLClassDefinitionNode; import org.apache.flex.compiler.tree.mxml.IMXMLClassNode; import org.apache.flex.compiler.tree.mxml.IMXMLComponentNode; import org.apache.flex.compiler.tree.mxml.IMXMLDataBindingNode; import org.apache.flex.compiler.tree.mxml.IMXMLDeclarationsNode; import org.apache.flex.compiler.tree.mxml.IMXMLDocumentNode; import org.apache.flex.compiler.tree.mxml.IMXMLEmbedNode; import org.apache.flex.compiler.tree.mxml.IMXMLEventSpecifierNode; import org.apache.flex.compiler.tree.mxml.IMXMLFactoryNode; import org.apache.flex.compiler.tree.mxml.IMXMLFileNode; import org.apache.flex.compiler.tree.mxml.IMXMLImplementsNode; import org.apache.flex.compiler.tree.mxml.IMXMLInstanceNode; import org.apache.flex.compiler.tree.mxml.IMXMLIntNode; import org.apache.flex.compiler.tree.mxml.IMXMLLiteralNode; import org.apache.flex.compiler.tree.mxml.IMXMLMetadataNode; import org.apache.flex.compiler.tree.mxml.IMXMLNode; import org.apache.flex.compiler.tree.mxml.IMXMLNumberNode; import org.apache.flex.compiler.tree.mxml.IMXMLObjectNode; import org.apache.flex.compiler.tree.mxml.IMXMLPropertySpecifierNode; import org.apache.flex.compiler.tree.mxml.IMXMLScriptNode; import org.apache.flex.compiler.tree.mxml.IMXMLStringNode; import org.apache.flex.compiler.tree.mxml.IMXMLStyleSpecifierNode; import org.apache.flex.compiler.tree.mxml.IMXMLUintNode; import org.apache.flex.compiler.tree.mxml.IMXMLVectorNode; import org.apache.flex.compiler.visitor.IBlockWalker; import org.apache.flex.compiler.visitor.mxml.IMXMLBlockWalker; /** * The base implementation for an MXML emitter. * * @author Erik de Bruin */ public class MXMLEmitter extends Emitter implements IMXMLEmitter { @Override public String postProcess(String output) { return output; } //-------------------------------------------------------------------------- // walkers //-------------------------------------------------------------------------- protected IMXMLBlockWalker walker; @Override public IBlockWalker getMXMLWalker() { return (IBlockWalker) walker; } @Override public void setMXMLWalker(IBlockWalker value) { walker = (IMXMLBlockWalker) value; } public MXMLEmitter(FilterWriter out) { super(out); } //-------------------------------------------------------------------------- @Override public void emitDeclarations(IMXMLDeclarationsNode node) { // visit tags final int len = node.getChildCount(); for (int i = 0; i < len; i++) { getMXMLWalker().walk(node.getChild(i)); } } @Override public void emitDocumentHeader(IMXMLFileNode node) { IMXMLDocumentNode dnode = node.getDocumentNode(); IClassDefinition cdef = dnode .getClassReference((ICompilerProject) walker.getProject()); write("<" + cdef.getBaseName()); emitPropertySpecifiers(dnode.getPropertySpecifierNodes(), true); writeNewline(">", true); } @Override public void emitDocumentFooter(IMXMLFileNode node) { IMXMLDocumentNode dnode = node.getDocumentNode(); IClassDefinition cdef = dnode .getClassReference((ICompilerProject) walker.getProject()); writeNewline("", false); write("</" + cdef.getBaseName() + ">"); } //-------------------------------------------------------------------------- @Override public void emitClass(IMXMLClassDefinitionNode node) { // fx:declarations IMXMLDeclarationsNode[] dnodes = node.getDeclarationsNodes(); if (dnodes != null) { for (IMXMLDeclarationsNode dnode : dnodes) { getMXMLWalker().walk(dnode); } } // fx:script IMXMLScriptNode[] snodes = node.getScriptNodes(); if (snodes != null) { for (IMXMLScriptNode snode : snodes) { getMXMLWalker().walk(snode); } } // "regular" tags emitPropertySpecifiers(node.getPropertySpecifierNodes(), false); } //-------------------------------------------------------------------------- @Override public void emitEventSpecifier(IMXMLEventSpecifierNode node) { } @Override public void emitInstance(IMXMLInstanceNode node) { IClassDefinition cdef = node .getClassReference((ICompilerProject) getMXMLWalker() .getProject()); String cname = cdef.getBaseName(); write("<"); write(cname); if (node.getID() != null && node.getID() != "") { write(ASEmitterTokens.SPACE); write("id"); write(ASEmitterTokens.EQUAL); write("\""); write(node.getID()); write("\""); } IMXMLPropertySpecifierNode[] pnodes = node.getPropertySpecifierNodes(); // attributes emitPropertySpecifiers(pnodes, true); write(">"); // child nodes emitPropertySpecifiers(pnodes, false); write("<"); write("/"); write(cname); write(">"); } @Override public void emitPropertySpecifier(IMXMLPropertySpecifierNode node) { if (!isMXMLContentNode(node)) // only for attributes { write(node.getName()); write(ASEmitterTokens.EQUAL); } getMXMLWalker().walk(node.getInstanceNode()); } @Override public void emitStyleSpecifier(IMXMLStyleSpecifierNode node) { if (!isMXMLContentNode(node)) // only for attributes { write(node.getName()); write(ASEmitterTokens.EQUAL); } getMXMLWalker().walk(node.getInstanceNode()); } @Override public void emitScript(IMXMLScriptNode node) { write("<script><![CDATA["); int len = node.getChildCount(); if (len > 0) { writeNewline("", true); for (int i = 0; i < len; i++) { getMXMLWalker().walk(node.getChild(i)); if (i == len - 1) indentPop(); writeNewline(ASEmitterTokens.SEMICOLON); } } write("]]></script>"); } //-------------------------------------------------------------------------- @Override public void emitObject(IMXMLObjectNode node) { final int len = node.getChildCount(); for (int i = 0; i < len; i++) { IASNode child = node.getChild(i); getMXMLWalker().walk(child); if (child instanceof IMXMLInstanceNode && i < len - 1) writeNewline(); } } @Override public void emitArray(IMXMLArrayNode node) { final int len = node.getChildCount(); for (int i = 0; i < len; i++) { IASNode child = node.getChild(i); getMXMLWalker().walk(child); if (child instanceof IMXMLInstanceNode && i < len - 1) writeNewline(); } } @Override public void emitBoolean(IMXMLBooleanNode node) { emitAttributeValue(node); } @Override public void emitInt(IMXMLIntNode node) { emitAttributeValue(node); } @Override public void emitNumber(IMXMLNumberNode node) { emitAttributeValue(node); } @Override public void emitString(IMXMLStringNode node) { emitAttributeValue(node); } @Override public void emitUint(IMXMLUintNode node) { emitAttributeValue(node); } //-------------------------------------------------------------------------- @Override public void emitLiteral(IMXMLLiteralNode node) { write(node.getValue().toString()); } //-------------------------------------------------------------------------- // Utils //-------------------------------------------------------------------------- public void emitPropertySpecifiers(IMXMLPropertySpecifierNode[] nodes, boolean emitAttributes) { if (nodes != null) { for (IMXMLPropertySpecifierNode cnode : nodes) { if (!isMXMLContentNode(cnode) && emitAttributes) { write(ASEmitterTokens.SPACE); getMXMLWalker().walk(cnode); } else if (isMXMLContentNode(cnode) && !emitAttributes) { getMXMLWalker().walk(cnode); } } } } protected void emitAttributeValue(IASNode node) { IMXMLLiteralNode cnode = (IMXMLLiteralNode) node.getChild(0); if (cnode.getValue() != null) { write("\""); getMXMLWalker().walk((IASNode) cnode); // Literal write("\""); } } protected boolean isMXMLContentNode(IMXMLNode node) { return node.getName().equals("mxmlContentFactory") || node.getName().equals("mxmlContent"); } public void emitFactory(IMXMLFactoryNode node) { IASNode cnode = node.getChild(0); write("\""); if (cnode instanceof IMXMLClassNode) { write(((IMXMLClassNode)cnode).getValue(getMXMLWalker().getProject()).getQualifiedName()); } write("\""); } public void emitComponent(IMXMLComponentNode node) { IASNode cnode = node.getChild(0); write("<fx:Component>"); if (cnode instanceof IMXMLClassNode) { getMXMLWalker().walk((IASNode) cnode); // Literal } write("</fx:Component>"); } public void emitMetadata(IMXMLMetadataNode node) { // ToDo (erikdebruin): implement metadata output } public void emitEmbed(IMXMLEmbedNode node) { // ToDo (erikdebruin): implement embed output } public void emitImplements(IMXMLImplementsNode node) { // ToDo (erikdebruin): implement implements output } public void emitVector(IMXMLVectorNode node) { // ToDo (erikdebruin): implement vector output } public void emitDatabinding(IMXMLDataBindingNode node) { // ToDo (erikdebruin): implement databinding output } }