Skip to content

Instantly share code, notes, and snippets.

@amacdougall
Created August 17, 2011 22:28
Show Gist options
  • Save amacdougall/1152808 to your computer and use it in GitHub Desktop.
Save amacdougall/1152808 to your computer and use it in GitHub Desktop.
Model.as, setValue refactoring
/**
* Sets the value targeted by the key to the value. Only handles key formats
* that have been seen "in the wild," but adding new ones is a cinch. Known
* formats so far:
*
* event
* event.card
* event.card.fonts
* event.card.sides.0.assets.0.propertyName
* event.card.side(paper,front,0).assets
* event.card.side(paper,front,0).asset(123abc)
* event.card.side(paper,front,0).asset(123abc).propertyName
*
* @param key The target path of the asset to be set, in one of the formats
* listed above.
* @param value The value to be set. May be any value JSON value.
* @param callback The ExternalInterface function to be called on completion.
* @param onRendered The ExternalInterface function to be called when rendered.
*
* @throws ArgumentError if no handler was ultimately found for the key.
*/
public function setValue_experimental(key:String, value:*, callback:String = null, onRendered:String=null):void
{
Debug.log("Model.setValue_experimental(): " + key + " -> " + JSON.encode(value));
Debug.indent();
/**
* With a key and an array of {pattern: RegExp, handler: Function}
* objects, call the handler function associated with the first
* matching regex pattern.
*/
function callMatchingHandler(key:String, mappings:Array):void {
var patternsTested:Array = [];
for each (var mapping:Object in mappings) {
if (mapping.pattern.test(key)) {
mapping.handler();
return;
} else {
patternsTested.push(mapping.pattern);
}
}
// if no successful match caused a return from this function...
Debug.unindent();
throw new ArgumentError("Model.setValue: found no matching handler for key \"" + key + "\"\n" +
"Patterns tested:\n" + patternsTested.join("\n"));
}
if (key.match(/^event\.card\.side/)) {
// define side variable if the key refers to one
var side:Side = null;
if (key.match(/^event\.card\.sides\.\d+/)) {
var sideIndexPattern:RegExp = /^event\.card\.sides\.(\d+)/;
var sideIndex:int = parseInt(key.match(sideIndexPattern)[1]);
side = event.card.sides[sideIndex];
} else if (key.match(/^event\.card\.side\(/)) {
var sideArgumentsPattern:RegExp = /^event\.card\.side\((\w+,\w+,\d+)\)/;
var sideArguments:Array = key.match(sideArgumentsPattern)[1].split(",");
side = event.card.side.apply(side, sideArguments);
}
if (!side) {
Debug.unindent();
throw new Error("Unable to find a side with arguments " + sideArguments.join(","));
}
}
if (key.match(/\.asset(s\.\d+|\()/)) { // e.g. ".assets.2" or ".asset("
var asset:Asset = null;
// define asset varaible if the key refers to one
if (key.match(/\.assets\.\d+\.\w+$/)) {
var assetIndexPattern:RegExp = /^event\.card\.sides\.\d+\.assets\.(\d+)/;
var assetIndex:int = parseInt(key.match(assetIndexPattern)[1]);
asset = side.assets[assetIndex];
} else if (key.match(/\.asset\(\w+\)/)) {
var uuid:String = key.match(/\.asset\((\w+)\)/)[1];
asset = side.asset(uuid);
}
if (!asset) {
Debug.unindent();
throw new Error("Unable to find an asset with uuid " + uuid);
}
}
callMatchingHandler(key, [
// e.g.: "event"
{ pattern: /^event$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern /^event$/");
event.updateData(value);
PP.instance.cache.create_version = value.create_version;
_lastJSONModel = JSON.encode(event);
/* If this is the first setValue call, _firstData will be false
* and we'll wait for JS to send an update call. Otherwise,
* fire Event.INIT.
*/
// TODO: rename to hasReceivedData or something.
if (_firstData) {
Debug.log("Model.setValue(): Dispatching Event.INIT");
dispatchEvent(new Event(Event.INIT));
} else {
_firstData = true;
}
}
},
// e.g.: "event.card"
{ pattern: /^event\.card$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern /^event\\.card$/");
event.card.updateData(value);
/* If this is the first setValue call, _firstData will be false
* and we'll wait for JS to send an update call. Otherwise,
* fire Event.INIT.
*/
// TODO: rename to hasReceivedData or something.
if (_firstData) {
Debug.log("Model.setValue(): Dispatching Event.INIT");
dispatchEvent(new Event(Event.INIT));
} else {
_firstData = true;
}
}
},
// e.g.: "event.card.fonts"
{ pattern: /^event\.card\.fonts$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern /^event\\.card\\.fonts$/");
event.card.fonts = value;
if (!app.rendering) {
PP.instance.cache.fontsChanged = true;
}
}
},
// e.g.: "event.card.sides.0.assets.0.asset"
// "event.card.sides.0.assets.2.image_url"
{ pattern: /^event\.card\.sides\.\d+\.assets\.\d+\.\w+$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern " +
"/^event\\.card\\.sides\\.\\d+\\.assets\\.\\d+\\.\\w+$/");
var propertyName:String = key.match(/\w+$/)[0];
if (propertyName == "color") {
asset[propertyName] = int(value);
} else {
asset[propertyName] = value;
}
invalidate([asset]);
}
},
// e.g.: "event.card.side(paper,front,0).assets"
{ pattern: /^event\.card\.side\(\w+,\w+,\d+\)\.assets$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern " +
"/^event\\.card\\.side\\(\\w+,\\w+,\\d+\\)\\.assets$/");
side.updateAssets(value);
invalidate(side.assets);
}
},
// e.g.: "event.card.side(paper,front,0).asset(123456abcdef)"
{ pattern: /^event\.card\.side\(\w+,\w+,\d+\)\.asset\(\w+\)$/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern " +
"/^event\\.card\\.side\\(\\w+,\\w+,\\d+\\)\\.asset\\(\\w+\\)$/");
asset.updateData(value);
invalidate([asset]);
}
},
// e.g.: "event.card.side(paper,front,0).asset(123456abcdef).color"
{ pattern: /^event\.card\.side\(\w+,\w+,\d+\)\.asset\(\w+\)\.\w+/,
handler: function():void {
Debug.log("Handling \"" + key + "\" with pattern " +
"/^event\\.card\\.side\\(\\w+,\\w+,\\d+\\)\\.asset\\(\\w+\\)\\.\\w+/");
var propertyName:String = key.match(/\w+$/)[0];
if (propertyName == "color") {
asset[propertyName] = parseInt(value);
} else {
asset[propertyName] = value;
}
invalidate([asset]);
}
}
]);
app.rendering = false;
callback && ExternalInterface.call(callback); // needs no arguments, says William C.
onRendered && _callbacks.push(onRendered);
Debug.unindent();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment