I am creating a method that will take a collection of different types (divs, spans..) and search it. I can't find a parameter to pass different collection types though. I tried IElementContainer and ElementCollections but I can't cast DivCollection to either. Is there another way?
The method that does the search:
private static ElementCollection searchCollections(IElementContainer ec, WACore.compStringInfo info)
{
if (info.componentIDName == WACore.componentIDs.Id.ToString())
{
return ec.Elements.Filter(Find.ById(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.Name.ToString())
{
return ec.Elements.Filter(Find.ByName(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.Title.ToString())
{
return ec.Elements.Filter(Find.ByTitle(info.componentIDValue));
}
else if (info.componentIDName == WACore.componentIDs.OuterText.ToString())
{
String str = info.componentIDValue.Substring(1, 6);
return ec.Elements.Filter(Find.ByText(new Regex(str)));
}
else
{
return null;
}
}
The caller(s):
return searchCollections((IElementContainer)doc.TextFields, info);
return searchCollections((IElementContainer)(doc.Divs), info);
return searchCollections((IElementContainer)doc.Spans, info);
Related
I am studying Ceylon and have question about it metamodel. I want to create some create some base class 'DataContainer' which allow to instantiate immutable classes with build-in equals-hash implementation:
e.g. Identifier(125, "ab") == Identifier(125, "ab")
So base class should collect all shared non-variable values and use this information in 'hash' an 'equals' methods.
I have wrote this code:
shared abstract class DataContainer(ClassDeclaration declaration) {
value members = {
for (i in declaration.memberDeclarations<ValueDeclaration>())
if (!i.variable, i.name != "hash", i.name != "string") i
};
variable Integer? hashCode = null;
shared actual Boolean equals(Object that) {
if (is DataContainer that) {
for (item in members) {
value thisMember = item.memberGet(this);
value thatMember = item.memberGet(that);
if (exists thisMember, exists thatMember) {
if (thisMember != thatMember) { return false; }
} else if (thisMember exists != thatMember exists) { return false; }
}
return true;
}
return false;
}
shared actual Integer hash => hashCode else (hashCode = calculateHash());
Integer calculateHash() {
variable value result = 0;
for(i in members) {
if (exists member = i.memberGet(this)) {
result = result.xor(member.hash);
}
}
return result;
}
}
class Identifier(shared Integer? id, shared String? name) extends DataContainer(`class`) {}
The Identifier class is the client of DataContainer. I like this solution in whole but I have to pass 'class' into the super class constructor because if I use 'class' inside DataContainer it doesn't see any members of subclass.
How can I obtain actual list of extended class's members in base class methods?
Something like 'this' doesn't work...
I found solution thanks to guys from Ceylon community. The function classDeclaration(this) from ceylon.language.meta should be used instead of 'class'.
This is the final code:
shared abstract class DataContainer() {
variable Integer? _hash = null;
variable ValueDeclaration[]? _members = null;
shared actual Boolean equals(Object that) {
if (is DataContainer that) {
for (i in members) {
value thisMember = i.memberGet(this);
value thatMember = i.memberGet(that);
if (exists thisMember, exists thatMember) {
if (thisMember != thatMember) { return false; }
} else if (thisMember exists != thatMember exists) { return false; }
}
return true;
}
return false;
}
shared actual Integer hash => _hash else (_hash = calculateHash());
ValueDeclaration[] members => _members else (_members = [
for (i in classDeclaration(this).memberDeclarations<ValueDeclaration>())
if (!i.variable, i.name != "string", i.name != "hash") i
]);
Integer calculateHash() {
variable Integer result = 0;
for (i in members) {
if (exists member = i.memberGet(this)) {
result = result.xor(member.hash);
}
}
return result;
}
}
class Identifier(shared Integer? number, shared String? name) extends DataContainer() {}
Adding to Alexander's formidable answer, I took the liberty to implement a string function as well so you can just print(myObj) and it renders nicely:
shared default actual String string {
value s = StringBuilder();
s.append(type(this).declaration.name).append(" { ");
for (i in members) {
value m = i.memberGet(this);
s.append(i.name).append(":");
s.append(if(exists m) then m.string else "<null>");
}
return s.append(" }").string;
}
I'm write this function:
public static String QueryString(string queryStringKey)
{
if (HttpContext.Current.Request.QueryString[queryStringKey] != null)
{
if (HttpContext.Current.Request.QueryString[queryStringKey].ToString() != string.Empty)
return HttpContext.Current.Request.QueryString.GetValues(1).ToString();
}
return "NAQ";
}
And i want to get just one value from querystring parameter.
for example i send "page" to my function and url is: "sth.com/?page=1&page=2"
and function return to me: "1,2" ; but i want first value: "1", How?
GetValues returns a string[] if the key exists. An array is zero based, so you get the first element by using array[0], you are using GetValues(1) in your code, i assume that you wanted the first.
You could also use the Enumerable.First extension method:
Request.QueryString.GetValues("page").First();
Since GetValues returns not an empty array but null if the key was not present you need to check that explicitely (FirstOrDefault doesn't work):
public static String QueryString(string queryStringKey)
{
if (HttpContext.Current != null && HttpContext.Current.Request != null)
{
string[] values = HttpContext.Current.Request.QueryString.GetValues("queryStringKey");
if (values != null) return values.First();
}
return "NAQ";
}
A better approach would be -
public static String QueryString(string queryStringKey)
{
if (HttpContext.Current!=null && HttpContext.Current.Request!=null && !string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[queryStringKey])
{
return HttpContext.Current.Request.QueryString.GetValues(queryStringKey).First();
}
return "NAQ";
}
I have ASP.NET application and want to use enum in if statement.
I get variable in this way:
string choice = (string)Session["export_choice"];
if(choice == <here goes enum>)
{
}
else
{
}
enum can have 2 string values only.
this is normally where I would use a switch:
myEnumType myEnumChoice;
if (Enum.TryParse(choice, out myEnumChoice))
{
switch(myEnumChoice)
{
case myEnumType.FirstEnum:
//doSomething();
break;
case myEnumType.SecondEnum:
//doSomethingElse();
break;
}
}
else
throw new ArgumentException(string.Format("Unexpected enum value: {0}", choice));
use
EnumChoice choice = (EnumChoice) Enum.Parse(typeof(ChumChoice), (string)Session["export_choice"] , true);
EnumChoice is enum type
you can use it like
if(choice== EnumChoice.X)
{
}
else
{
}
I have some binary data and I can't store it in a string, as such I'm using a ByteArray.
The problem is that I need some functionality that comes with strings, to be specific I need the charAt, substr, indexOf and substring methods.
These would be fairly easy to implement. I can post the code if wanted. Is the data string-like? Or does it need to be treated as arbitrary binary? In either case, how wide are characters (e.g. 8-bit, 16-bit)?
public static function charAt(bytes:ByteArray, index:int):String {
if (bytes.length <= index) return null;
return String.fromCharCode(bytes[index]);
}
public static function substr(bytes:ByteArray, start:int, length:int=0):String {
var res:ByteArray = bytes.readBytes(bytes, start, length);
return res.toString();
}
public static function substring(bytes:ByteArray, start:int, end:int=0):String {
return substr(bytes, start, end-start);
}
public static function indexOf(bytes:ByteArray, str:String):int {
for (var i:int=0; i<bytes.length; i++) {
var strPos:int = 0;
while (String.fromCharCode(bytes[i+strPos]) == str.charAt(strPos)) {
strPos++;
if (strPos == str.length) return i;
}
}
return -1;
}
I want to check in my function if a passed argument of type object is empty or not. Sometimes it is empty but still not null thus I can not rely on null condition. Is there some property like 'length'/'size' for flex objects which I can use here.
Please help.
Thanks in advance.
If you mean if an Object has no properties:
var isEmpty:Boolean = true;
for (var n in obj) { isEmpty = false; break; }
This is some serious hack but you can use:
Object.prototype.isEmpty = function():Boolean {
for(var i in this)
if(i != "isEmpty")
return false
return true
}
var p = {};
trace(p.isEmpty()); // true
var p2 = {a:1}
trace(p2.isEmpty()); // false
You can also try:
ObjectUtil.getClassInfo(obj).properties.length > 0
The good thing about it is that getClassInfo gives you much more info about the object, eg. you get the names of all the properties in the object, which might come in handy.
If object containes some 'text' but as3 doesn't recognize it as a String, convert it to string and check if it's empty.
var checkObject:String = myObject;
if(checkObject == '')
{
trace('object is empty');
}
Depends on what your object is, or rather what you expect it to have. For example if your object is supposed to contain some property called name that you are looking for, you might do
if(objSomeItem == null || objSomeItem.name == null || objSomeItem.name.length == 0)
{
trace("object is empty");
}
or if your object is actually supposed to be something else, like an array you could do
var arySomeItems = objSomeItem as Array;
if(objSomeItem == null || arySomeItems == null || arySomeItems.length == 0)
{
trace("object is empty");
}
You could also use other ways through reflection, such as ObjectUtil.getClassInfo, then enumerate through the properties to check for set values.... this class help:
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
public class ReflectionUtils
{
/** Returns an Array of All Properties of the supplied object */
public static function GetVariableNames(objItem:Object):Array
{
var xmlPropsList:XMLList = describeType(objItem)..variable;
var aryVariables:Array = new Array();
if (xmlPropsList != null)
{
for (var i:int; i < xmlPropsList.length(); i++)
{
aryVariables.push(xmlPropsList[i].#name);
}
}
return aryVariables;
}
/** Returns the Strongly Typed class of the specified library item */
public static function GetClassByName($sLinkageName:String):Class
{
var tObject:Class = getDefinitionByName($sLinkageName) as Class;
return tObject;
}
/** Constructs an instance of the speicified library item */
public static function ConstructClassByName($sLinkageName:String):Object
{
var tObject:Class = GetClassByName($sLinkageName);
//trace("Found Class: " + tMCDefinition);
var objItem:* = new tObject();
return objItem;
}
public static function DumpObject(sItemName:String, objItem:Object):void
{
trace("*********** Object Dump: " + sItemName + " ***************");
for (var sKey:String in objItem)
{
trace(" " + sKey +": " + objItem[sKey]);
}
}
//}
}
Another thing to note is you can use a simple for loop to check through an objects properties, thats what this dumpobject function is doing.
You can directly check it as follow,
var obj:Object = new Object();
if(obj == null)
{
//Do something
}
I stole this from a similar question relating to JS. It requires FP 11+ or a JSON.as library.
function isEmptyObject(obj){
return JSON.stringify(obj) === '{}';
}
can use use the hasProperty method to check for length
var i:int = myObject.hasProperty("length") ? myObject.length: 0;