blob: fee9d68ec1cf46791aa0359ba59a03fa66a4d97c [file] [log] [blame]
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<js:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:js="library://ns.apache.org/royale/basic"
xmlns:local="*"
initComplete="startup()">
<fx:Script>
<![CDATA[
import org.apache.royale.storage.PermanentStorage;
import org.apache.royale.storage.events.FileEvent;
import org.apache.royale.storage.events.FileErrorEvent;
import org.apache.royale.storage.file.IDataInput;
import org.apache.royale.storage.file.IDataOutput;
import org.apache.royale.reflection.beads.JSONReviver;
private function startup():void
{
trace("Starting up");
}
public function set ready(value:Boolean):void
{
status.text = "Now Ready";
}
private var json:Object;
private var subClasses:Object = {};
private var subObjects:Array = [];
private function onSave():void
{
try {
json = JSON.parse(contentField.text);
}
catch (e:Error)
{
status.text = "Error parsing JSON result"
}
writeClass(json, writeFileNameField.text);
}
private function writeClass(obj:Object, className:String):void
{
obj["__JSON2ASVO__"] = className; // mark as seen so we don't loop on circular references
status.text = "Writing class: " + className;
var storage:PermanentStorage = new PermanentStorage();
var firstChar:String;
var key:String;
var useFile:String = className + ".as";
var useContent:String = "package\n{\n";
if (generateBinding.selected && !immutable.selected)
{
useContent += "import org.apache.royale.events.EventDispatcher;\n";
useContent += "import org.apache.royale.events.ValueChangeEvent;\n";
}
useContent += "[RemoteClass(alias='" + className + "')]\n";
if (generateBinding.selected && !immutable.selected)
useContent += "public class " + className + " extends EventDispatcher\n{\n";
else
useContent += "public class " + className + "\n{\n";
useContent += " public static const key:String = \"" + JSONReviver.generateKey(obj) + "\";\n\n";
for (var p:String in obj)
{
if (p == "__JSON2ASVO__") continue;
var value:Object = obj[p];
var typeName:String;
var typeString:String;
if (value is Array)
{
typeString = "Array";
if (value.length > 0)
{
value = value[0];
if (!(value is String ||
value is Number ||
value === true ||
value === false))
{
key = JSONReviver.generateKey(value);
if (!subClasses[key])
{
firstChar = p.charAt(0).toUpperCase();
typeName = className + firstChar + p.substr(1);
subClasses[key] = typeName;
subObjects.push(value);
}
}
}
}
else if (value is String)
{
typeString = "String";
}
else if (value is Number)
{
if (Math.round(value as Number) === value)
typeString += "int";
else
typeString += "Number";
}
else if (value === true || value === false)
{
typeString += "Boolean";
}
else if (value === null)
{
typeString += "Object /* was null */";
}
else
{
typeName = value["__JSON2ASVO__"];
if (typeName)
typeString = typeName;
else
{
key = JSONReviver.generateKey(value);
typeName = subClasses[key];
if (typeName)
typeString = typeName;
else
{
firstChar = p.charAt(0).toUpperCase();
typeName = className + firstChar + p.substr(1);
subClasses[key] = typeName;
typeString = typeName;
subObjects.push(value);
}
}
}
useContent += " private var _" + p + ":" + typeString + ";\n";
if (generateBinding.selected)
{
useContent += " [Bindable(\"";
if (!immutable.selected)
useContent += "valueChange";
else
useContent += "__NoChangeEvent__";
useContent += "\")]\n";
}
useContent += " public function get " + p + "():" + typeString + "\n";
useContent += " {\n return _" + p + ";\n }\n";
useContent += " public function set " + p + "(__v__:" + typeString + "):void\n";
useContent += " {\n";
if (generateBinding.selected && !immutable.selected)
{
useContent += " if (_" + p + " == __v__) return;\n";
useContent += " var e:ValueChangeEvent = ValueChangeEvent.createUpdateEvent(this, _" + p + ", __v__);\n";
useContent += " _" + p + " = __v__;\n";
useContent += " dispatchEvent(e);\n";
}
else
useContent += " _" + p + " = __v__;\n";
useContent += " }\n\n";
}
useContent += "}\n"; // end class
useContent += "}\n"; // end package
storage.addEventListener("WRITE", handleSave);
storage.addEventListener("ERROR", handleSaveError);
storage.writeTextToDataFile(useFile, useContent);
}
private function handleSave(event:FileEvent):void
{
var foundOne:Boolean = false;
while (subObjects.length)
{
var value:Object = subObjects.shift();
if (value["__JSON2ASVO__"]) continue; // already seen it
var key:String = JSONReviver.generateKey(value);
var className:String = subClasses[key];
foundOne = true;
writeClass(value, className);
break;
}
if (!foundOne)
status.text = "Done!";
}
private function handleSaveError(event:FileErrorEvent):void
{
status.text = "Error: "+event.errorMessage;
}
]]>
</fx:Script>
<fx:Style>
.labelStyle {
color: #9999FF;
}
.contentStyle {
font-size: 18pt;
}
</fx:Style>
<js:beads>
<js:ViewDataBinding />
</js:beads>
<js:VGroup>
<js:Label text="Generate ActionScript ValueObjects (Data Classes) from a JSON result" width="100%" />
<js:Spacer height="20" />
<js:Label id="status" text="** APP STATUS HERE **" />
<js:Spacer height="20" />
<js:Label text="Generated classes will be written to the application storage folder" width="100%" />
<js:HGroup>
<js:Label text="Output Class Name:" className="labelStyle" />
<js:TextInput id="writeFileNameField" text="ValueObject" width="200"/>
</js:HGroup>
<js:Label text="Sub-Objects will be given a class name based on the field where it was discovered." width="100%" />
<js:Label text="So if you set Output Class Name to 'Foo' and the JSON result has a sub-object" width="100%" />
<js:Label text="in a 'bar' field, that sub-object will have the class name FooBar." width="100%" />
<js:Spacer height="20" />
<js:Label text="Enter JSON result:" className="labelStyle" />
<js:TextArea id="contentField" width="100%" height="300" />
<js:HGroup>
<js:CheckBox id="generateBinding" text="Bindable" selected="true"/>
<js:Spacer width="20" />
<js:CheckBox id="immutable" text="Immutable"/>
</js:HGroup>
<js:TextButton text="Generate Classes" click="onSave()" />
</js:VGroup>
</js:View>