Use variable name in StringUtil.substitue in Actionscript - apache-flex

If I have the following code:
var value : String = StringUtil.substitute("The value {0} requested is {1}", user, value);
How can I use the variable name instead of using {0} and {1} in the code.
Please advice. Thanks.
Edit:
The above code is quoted from http://www.rialvalue.com/blog/2010/05/10/string-templating-in-flex/.
It says that "Also note that we’re substituting the parameters using the order, it’d would fairly easy to do a named-parameter subsitution instead (i.e. using tokens like ${var1})". Therefore, I think it may be very easy to do that, but I don't know how to do.

Looks like it's not possible. And kind of makes sense that it allows zero based ints only, since you're passing a variable number of parameters that you're not identifying (except for their relative position in the params list).
Here's a piece of code that will replace tokens by name:
public static function replacePlaceholders(input:String,replacementMap:Object):String {
// '${', followed by any char except '}', ended by '}'
return input.replace(/\${([^}]*)}/g,function():String {
return replaceEntities(arguments,replacementMap);
});
}
private static function replaceEntities(regExpArgs:Array,map:Object):String {
var entity:String = String(regExpArgs[0]);
var entityBody:String = String(regExpArgs[1]);
return (map[entityBody]) ? map[entityBody] : entity;
}
Use:
var test:String = "Hello there ${name}, how is the ${noun} today?";
var replacementMap:Object = {
name : "YOUR_NAME_HERE",
noun : "YOUR_NOUN_HERE"
};
trace(StringUtils.replacePlaceholders(test,replacementMap));
The format I'm using for the placeholders is ${placeholdername}, since it's safer, I think. But if you want to remove the dollar sign, change the regexp accordingly.

Related

Serilog Custom Sink Formatting Issue with Serilog LogEventPropertyValue

I'm having to create my own custom sink because none of the ones currently available give me what I need.
Issue I have is when fetching the key/value pair Value from the logEvent message in the Emit Method, the value is wrapped with quotation marks & backslashes.
I've tried converting the out value from the dictionary into a string and then removing the unwanted attributes but nothing is working for me.
Method in my Custom Sink Class:
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value))
{
// Regex.Replace((value.ToString() ?? "").Replace("'", #"\'").Trim(), #"[\r\n]+", " "); // Not working
var notWorking = value.ToString();
var formattedValueNotWorking = value.ToString().Replace("\r\n", "\\r\\n");
}
}
It just seems that any attempted formatting of the key/value pair Value is ignored: You see that the example string value System is wrapped with a \"System\"
All I want is the actual string, not the backslashes or quotation marks that is wrapped around the string.
Creating my own sink is a hard enough task and I just want to keep things simple, have spent two days trying to understand the wider picture in message formatting but with custom sinks it gets too complicated and bloated coding for what I need. All the other standard message structure attributes are rendering OK, such as message / level / timestamp etc, it's just fine tuning the rendering of the propertie values I require in order to save these values into their own columns in my DB.
You need to unwrap the string from the enclosing ScalarValue:
// using Serilog.Events;
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value) &&
value is ScalarValue sv &&
sv.Value is string rawValue)
{
// `rawValue` is what you're looking for
Looks like I just needed to use the correct syntax for string replace:
public void Emit(LogEvent logEvent)
{
var properties = logEvent.Properties;
Serilog.Events.LogEventPropertyValue value;
if (properties.TryGetValue("logEventCategory", out value))
{
var formattedValueWorking = value.ToString().Replace("\"", "");
var test = formattedValueWorking;
}
}

How do I create the correct KeyboardEvent objects for a given string of text?

I'd like to simulate some keyboard input by dispatching KeyboardEvent objects manually. Creating such events involves passing a key code.
Alas, I only have a given string
const text: String = "Hello";
I can easily get the char code using String::charCodeAt, but how can I get the key code? For any given character (say: "H") there may be just a single key code, a key code plus some modifier (in this case: Shift + keycode_of_h) or even multiple key codes. Is there maybe a way to get the key code for a given char code (possibly by considering the keyboard mapping of the user)?
This isn't too difficult but it will just take a little bit to set up.
First create a dictionary or Object mapping the UTF-8 values to key values like this:
var keyCodes:Dictionary = new Dictionary();
keyCodes[49] = Keyboard.NUMBER_1; //1
// add the rest of the mappings...
Then because you need to specify SHIFT
var shiftedKeyCodes:Dictionary = new Dictionary();
shiftedKeyCodes[33] = Keyboard.NUMBER_1; //!
// add the rest of the shifted mappings
Then create a utility function like this:
public function charCodeToKeyboardEvent(charCode:int):KeyboardEvent{
var event:KeyboardEvent = new KeyboardEvent(KeyboardEvent.KEY_UP);
event.charCode = charCode;
if(keyCodes[charCode]){
event.keyCode = keyCodes[charCode];
} else if (shiftedKeyCodes[charCode]){
event.keyCode = shiftedKeyCodes[charCode];
event.shiftKey = true;
} else {
return null;
}
return event;
}
Then loop through your string and do this:
for(var i:int = 0; i < myString.length; i++){
dispatchEvent(charCodeToKeyboardEvent(myString.charCodeAt(i)));
}
EDIT: I updated this to use the constants on the Keyboard class so that it will work independent of device or operating system.
It turns out that I didn't need a 100% correct KeyboardEvent in the first place. Instead, there were two things I was missing:
A flash.events.TextEvent needs to be dispatched for plain text (like "Hello") input.
The events need to be dispatched to the embedded edit control which can be accessed using the textDisplay property.

How to to find a domain name inside a query string value

I think regular expressions might be able to accomplish this, if not then string manipulation is also a viable solution.
I need to turn the following inputs:
"http://open.thumbshots.org/image.pxf?url=www.party.com"
"http://www.xclicks.net/sc/ct.php?s=9971&l=http%3A//www.google.com/imgres%3F"
"http://whos.amung.us/pingjs/?k=yvybju40twbs&t=Mudswimmer%3A%20Spam%20%26%20Crap%3A%20Http%3AUniversity.com%3A%20No%20Animals%20Allowed..&c=c&y=htt"
into the following outputs:
"party.com"
"google.com"
"University.com"
I am not trying to get the host name of the URL, I want the the second domain, the one in the query string.
With everything that involves regular expressions there is a degree of uncertainty, for me at least, but giving your three inputs the following code works:
string[] urls = new string[]
{
"http://open.thumbshots.org/image.pxf?url=www.party.com",
"http://www.xclicks.net/sc/ct.php?s=9971&l=http%3A//www.google.com/imgres%3F",
"http://whos.amung.us/pingjs/?k=yvybju40twbs&t=Mudswimmer%3A%20Spam%20%26%20Crap%3A%20Http%3AUniversity.com%3A%20No%20Animals%20Allowed..&c=c&y=htt"
};
foreach (var url in urls)
{
var result = HttpUtility.ParseQueryString(new Uri(url, UriKind.Absolute).Query);
foreach (string item in result)
{
string value = result.GetValues(item).Single();
const string DomainNamePattern = "(?:www\\.|\\b)(?<domain>([a-z0-9]([-a-z0-9]*[a-z0-9])?\\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(cat|com|coop|c[acdfghiklmnorsuvxyz])|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))";
var match = Regex.Match(
value,
DomainNamePattern,
RegexOptions.IgnoreCase);
if (match.Success)
{
string domain = match.Groups["domain"].Value;
Console.WriteLine(domain);
}
}
}
The regular expression used was adapted from here.
If you run this you get the following output:
// party.com
// google.com
// University.com
If your link always contain the url querystring key then you can simple get this by
String url = Request.QueryString["url"].ToString();
This will retrun the value of url.

AS3: Whats determines the order of: for..in

OK I am looping through the properties in an object like so:
private var _propsList:Object = {'Type':'product_type'
,'Kind':'product_type_sub'
,'Stone':'primary_stone'
,'Stone Color':'primary_stone_sub'
,'Metal':'metal_type'
,'Brand':'product_brand'};
for(key in _propsList)
{
val = _propsList[key];
trace(key +" = "+ val);
}
I am expecting the first trace to be Type = property_type since that is the first one defined in the array, however it is coming up random everytime. I guess this is because my keys are strings and not integers, however is there a way to specify the order it loops through them?
Thanks!!
You can't rely on for (v in someObject) ... to return things in a predictable order, no.
Depending on your specific situation, you could just use an array to hold the keys, and just iterate through that:
private var keys:Array = ["Type", "Kind", "Stone", "Stone Color", "Metal", "Brand"];
private function iterate():void
{
for each (var k:String in keys)
{
trace(_propsList[k]);
}
}
Maybe a bit obvious or non-elegant, but it'd get the job done. :)
you could hack it by classing-out your "_propsList" object creating an array inside of the newly created PropsList class that references the properties in order. At that point, you could run a FOR loop on the array and get your properties in order.
OR, you could have a function inside that new class that would return an Array of those properties. like this:
public function getProps():Array {
return [myPropertyOne, myPropertyTwo, myPropertyThree];
}
In general, I think this is a case where you shouldn't depend on a particular behavior from the framework/language you are using. This type of behavior is generally poorly documented and can change from version to version.
If you really need a specific retrieval order, I would create a wrapper class as jevinkones suggested above. Maybe there's even a utility class in the framework somewhere to accomplish this (Dictionary, etc.?)
HTH,
Karthik
I found this link that gives some background:
Subtle Change in for..in Loops for ActionScript 3
This question is actually a dup of this one.
How about using an array representation like this:
var _propsList:Array = [
['Type', 'product_type'],
['Kind', 'product_type_sub'],
['Stone', 'primary_stone'],
['Stone Color', 'primary_stone_sub'],
['Metal', 'metal_type'],
['Brand', 'product_brand']
];
for(var i in _propsList) {
var elem = _propsList[i];
var key = elem[0];
var val = elem[1]
}

E4X: Use string as attribute name in expression?

I have a function that has this line:
var returnString:String = items[0].#month;
#month is an attibute on an XML node like so:
<xmlnode month="JAN"/>
OK but I need to abstract the attribute name so I can pass a string to the function and get the contents of the attribute with the name matching the string I passed. So for example If I call the function like this function("stone") it returns items[0].#stone. I hope this is clear.
Does anyone know how to do what I am after?
Thanks.
You'll want to use attribute('stone') rather than #stone, its the same thing, #stone is just a shorthand way of writing it.
You can write this as:
var attrName:String = "month";
return items[0].#[ attrName ];
not only that, but if you ever want to assign a value to an attribute using a variable for the attribute name, you can do this (although it is not documented) like so:
public function setAttr(obj:XML, attrName:String, value:String):void{
obj.#[attrName] = value;
}

Resources