| /* |
| * |
| * 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.royale.compiler.internal.codegen.js.royale; |
| |
| import org.apache.royale.compiler.codegen.ISubEmitter; |
| import org.apache.royale.compiler.codegen.mxml.js.IMXMLJSEmitter; |
| import org.apache.royale.compiler.internal.codegen.as.ASEmitterTokens; |
| import org.apache.royale.compiler.internal.codegen.js.goog.JSGoogEmitterTokens; |
| import org.apache.royale.compiler.internal.codegen.mxml.MXMLSubEmitter; |
| import org.apache.royale.compiler.internal.codegen.mxml.royale.MXMLDescriptorSpecifier; |
| import org.apache.royale.compiler.internal.codegen.mxml.royale.MXMLEventSpecifier; |
| import org.apache.royale.compiler.internal.projects.RoyaleJSProject; |
| |
| public class JSRoyaleBasicMXMLDescriptorEmitter extends MXMLSubEmitter implements ISubEmitter<MXMLDescriptorSpecifier> |
| { |
| private boolean useGoogReflectObjectProperty = false; |
| |
| public JSRoyaleBasicMXMLDescriptorEmitter(IMXMLJSEmitter emitter) |
| { |
| super(emitter); |
| } |
| |
| @Override |
| public void emit(MXMLDescriptorSpecifier root) |
| { |
| RoyaleJSProject project = (RoyaleJSProject) getMXMLWalker().getProject(); |
| useGoogReflectObjectProperty = project.config != null && project.config.getMxmlReflectObjectProperty(); |
| outputDescriptorSpecifier(root, true); |
| } |
| |
| //--------------------------------- |
| // writeSimpleDescriptor |
| //--------------------------------- |
| |
| protected void writeSimpleDescriptor(String name, String type, String value, |
| boolean writeNewline) |
| { |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| write(name); |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| writeDelimiter(writeNewline); |
| |
| if (type != null) |
| { |
| write(type); |
| writeDelimiter(writeNewline); |
| } |
| |
| write(value); |
| } |
| |
| //--------------------------------- |
| // writeDelimiter |
| //--------------------------------- |
| |
| protected void writeDelimiter(boolean writeNewline) |
| { |
| if (writeNewline) |
| writeNewline(ASEmitterTokens.COMMA); |
| else |
| writeToken(ASEmitterTokens.COMMA); |
| } |
| |
| //--------------------------------- |
| // outputDescriptorSpecifier |
| //--------------------------------- |
| |
| private void outputDescriptorSpecifier(MXMLDescriptorSpecifier root, boolean writeNewline) |
| { |
| if (root.isTopNode) |
| { |
| int count = 0; |
| for (MXMLDescriptorSpecifier md : root.propertySpecifiers) |
| { |
| if (md.name != null) |
| count++; |
| } |
| |
| write(count + ""); |
| writeNewline(ASEmitterTokens.COMMA); |
| } |
| |
| outputPropertySpecifiers(root, writeNewline); |
| |
| if (!root.isProperty) |
| { |
| outputStyleSpecifiers(root, writeNewline); |
| |
| // TODO (erikdebruin) not yet implemented in Royale |
| //outputEffectSpecifiers(writeNewline); |
| |
| outputEventSpecifiers(root, writeNewline); |
| |
| if (!root.isTopNode) |
| { |
| writeDelimiter(writeNewline); |
| |
| if (root.childrenSpecifier == null) |
| write(ASEmitterTokens.NULL); |
| else |
| outputChildren(root.childrenSpecifier, writeNewline); |
| } |
| |
| boolean isLastChild = root.parent != null |
| && root.parent.propertySpecifiers.indexOf(root) == root.parent.propertySpecifiers |
| .size() - 1; |
| |
| if (!isLastChild && !root.isTopNode) |
| writeDelimiter(writeNewline); |
| } |
| } |
| |
| //--------------------------------- |
| // outputPropertySpecifiers |
| //--------------------------------- |
| |
| private void outputPropertySpecifiers(MXMLDescriptorSpecifier root, boolean writeNewline) |
| { |
| MXMLDescriptorSpecifier model = null; // model goes first |
| MXMLDescriptorSpecifier beads = null; // beads go last |
| |
| for (MXMLDescriptorSpecifier md : root.propertySpecifiers) |
| { |
| if (md.name != null && md.name.equals("model")) |
| { |
| model = md; |
| break; |
| } |
| } |
| |
| if (model != null) |
| { |
| outputPropertySpecifier(model, writeNewline); |
| } |
| |
| for (MXMLDescriptorSpecifier md : root.propertySpecifiers) |
| { |
| if (md.name != null) |
| { |
| if (!md.name.equals("model") && !md.name.equals("beads")) |
| outputPropertySpecifier(md, writeNewline); |
| else if (md.name.equals("beads")) |
| beads = md; |
| } |
| } |
| |
| if (beads != null) |
| { |
| outputPropertySpecifier(beads, writeNewline); |
| } |
| } |
| |
| //--------------------------------- |
| // outputEventSpecifiers |
| //--------------------------------- |
| |
| private void outputEventSpecifiers(MXMLDescriptorSpecifier root, boolean writeNewline) |
| { |
| // number of events |
| int count = 0; |
| for (MXMLEventSpecifier me : root.eventSpecifiers) |
| { |
| if (me.name != null) |
| count++; |
| } |
| write(count + ""); |
| |
| for (MXMLEventSpecifier me : root.eventSpecifiers) |
| { |
| writeDelimiter(writeNewline); |
| outputEventSpecifier(me, writeNewline); |
| } |
| } |
| |
| //--------------------------------- |
| // outputStyleSpecifiers |
| //--------------------------------- |
| |
| private void outputStyleSpecifiers(MXMLDescriptorSpecifier root, boolean writeNewline) |
| { |
| // TODO (erikdebruin) not yet implemented in Royale |
| |
| write("0"); |
| writeDelimiter(writeNewline); |
| } |
| |
| //--------------------------------- |
| // outputPropertySpecifier |
| //--------------------------------- |
| |
| private void outputPropertySpecifier(MXMLDescriptorSpecifier specifier, boolean writeNewline) |
| { |
| if(specifier.isProperty) |
| { |
| if(useGoogReflectObjectProperty) |
| { |
| write(JSGoogEmitterTokens.GOOG_REFLECT_OBJECTPROPERTY); |
| write(ASEmitterTokens.PAREN_OPEN); |
| } |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| write(specifier.name); |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| if(useGoogReflectObjectProperty) |
| { |
| MXMLDescriptorSpecifier parentSpecifier = specifier.parent; |
| String id = (parentSpecifier.id != null) ? parentSpecifier.id : parentSpecifier.effectiveId; |
| write(ASEmitterTokens.COMMA); |
| write(ASEmitterTokens.SPACE); |
| write(ASEmitterTokens.THIS); |
| if (id != null) |
| { |
| write(ASEmitterTokens.MEMBER_ACCESS); |
| write(id); |
| } |
| write(ASEmitterTokens.PAREN_CLOSE); |
| } |
| } |
| else |
| { |
| write(specifier.name); |
| } |
| writeDelimiter(writeNewline); |
| |
| if (specifier.isProperty) |
| { |
| if (specifier.value != null) |
| { |
| write(ASEmitterTokens.TRUE); |
| writeDelimiter(writeNewline); |
| // need to do other escaping here? |
| // restrict="0-9.\" |
| if (specifier.value.endsWith("\\'") && !specifier.value.endsWith("\\\\'")) |
| { |
| specifier.value = specifier.value.substring(0, specifier.value.length() - 1) + "\\'"; |
| } |
| write(specifier.value); |
| } |
| else |
| { |
| write((specifier.hasArray) ? ASEmitterTokens.NULL : ASEmitterTokens.FALSE); |
| writeDelimiter(writeNewline); |
| write(ASEmitterTokens.SQUARE_OPEN); |
| indentPush(); |
| writeNewline(); |
| outputDescriptorSpecifier(specifier, writeNewline); |
| indentPop(); |
| writeNewline(); |
| write(ASEmitterTokens.SQUARE_CLOSE); |
| } |
| |
| if (specifier.parent != null) |
| writeDelimiter(writeNewline); |
| } |
| else |
| { |
| for (MXMLDescriptorSpecifier md : specifier.propertySpecifiers) |
| { |
| if (md.name != null && md.name.equals("mxmlContent")) |
| { |
| specifier.childrenSpecifier = md; |
| specifier.propertySpecifiers.remove(md); |
| break; |
| } |
| } |
| |
| if (specifier.id != null || specifier.effectiveId != null) |
| { |
| write(specifier.propertySpecifiers.size() + 1 + ""); |
| writeDelimiter(writeNewline); |
| String idPropName = (specifier.effectiveId != null) ? "_id" : "id"; |
| String id = (specifier.id != null) ? specifier.id : specifier.effectiveId; |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| write(idPropName); |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| writeDelimiter(writeNewline); |
| write(ASEmitterTokens.TRUE); |
| writeDelimiter(writeNewline); |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| write(id); |
| write(ASEmitterTokens.SINGLE_QUOTE); |
| writeDelimiter(writeNewline); |
| } |
| else |
| { |
| write(specifier.propertySpecifiers.size() + ""); |
| writeDelimiter(writeNewline); |
| } |
| |
| outputDescriptorSpecifier(specifier, writeNewline); |
| } |
| } |
| |
| //--------------------------------- |
| // outputEventSpecifier |
| //--------------------------------- |
| |
| public void outputEventSpecifier(MXMLEventSpecifier specifier, boolean writeNewline) |
| { |
| String handler = ASEmitterTokens.THIS.getToken() |
| + ASEmitterTokens.MEMBER_ACCESS.getToken() + specifier.eventHandler; |
| if (MXMLEventSpecifier.nameMap.contains(specifier.name)) |
| specifier.name = specifier.name.toLowerCase(); |
| else if (specifier.name.equals("doubleClick")) |
| specifier.name = "dblclick"; |
| else if (specifier.name.equals("mouseWheel")) |
| specifier.name = "wheel"; |
| writeSimpleDescriptor(specifier.name, null, handler, writeNewline); |
| } |
| |
| //--------------------------------- |
| // outputChildren |
| //--------------------------------- |
| |
| private void outputChildren(MXMLDescriptorSpecifier children, boolean writeNewline) |
| { |
| write(ASEmitterTokens.SQUARE_OPEN.getToken()); |
| if(writeNewline) |
| { |
| indentPush(); |
| writeNewline(); |
| } |
| outputDescriptorSpecifier(children, writeNewline); |
| if(writeNewline) |
| { |
| indentPop(); |
| writeNewline(); |
| } |
| write(ASEmitterTokens.SQUARE_CLOSE.getToken()); |
| } |
| |
| } |