I have the below abstract class where character_1, character_2, character_3 are decleared.
public abstract class Properties {
public static final String character_1 = "//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']";
public static final String character_2 = "//*[#class='character-nav-slide-normal'][#alt='PEPPA']";
public static final String character_3 = "//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']";
}
How can I parameterise that and passing through to properties.
String[] myStringArray = {"character_1","character_2","character_3"};
for (int i = 0; i < myStringArray.length; i++)
{
String value = myStringArray[i];
String altvalue = driver.findElement(By.xpath(Properties.value)).getAttribute("alt");
System.out.print(altvalue);
}
I'd say the easiest is to use a HashMap<String, String>.
public class Properties { //no particular use to make this class abstract
public static final Map<String, String> characters;
static
{
characters = new HashMap<String, String>();
characters.put("character_1", "//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']");
characters.put("character_2", "//*[#class='character-nav-slide-normal'][#alt='PEPPA']");
characters.put("character_3", "//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']");
}
}
//somewhere else...
String[] myStringArray = {"character_1","character_2","character_3"};
for (String stringArrayString : myStringArray)
{
String xPath = Properties.characters.get(stringArrayString);
String altvalue = driver.findElement(By.xpath(xPath)).getAttribute("alt");
System.out.print(altvalue);
}
You can easily use above code to solve your problem.
However, your quote indicates that you already have something in mind:
I need how to send the value (i.e myStringArray[i] ) to Properties.
???????? so that when i = 0, String altvalue =
driver.findElement(By.xpath(Properties.character_1)).getAttribute("alt");
when i=1 , String altvalue =
driver.findElement(By.xpath(Properties.character_2)).getAttribute("alt");
like that.
While it is possible with reflection, it is heavily discouraged: you lose compile-time type safety, it causes bugs when refactoring, and performance is slower.
You could use an enum. Something along the lines of
public enum Properties {
CHARACTER_1("//*[#class='character- nav-slide-normal'][#alt='CHARLIE E LOLA']"),
CHARACTER_2("//*[#class='character-nav-slide-normal'][#alt='PEPPA']"),
CHARACTER_3("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_4("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_5("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_6("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']"),
CHARACTER_7("//*[#class='character-nav-slide-normal'][#alt='FESTA HI-5']");
private String xpath;
Properties(String xpath) {
this.xpath = xpath;
}
public String getXpath() {
return xpath;
}
}
Example
// Selective properties
Properties[] selectiveProperties = {Properties.CHARACTER_1, Properties.CHARACTER_3, Properties.CHARACTER_6, Properties.CHARACTER_7};
for (Properties property : selectiveProperties) {
String altvalue = driver.findElement(By.xpath(property.getXpath())).getAttribute("alt");
System.out.print(altvalue);
}
//Iterate through all the properties
for (Properties property : Properties.values()) {
String altvalue = driver.findElement(By.xpath(property.getXpath())).getAttribute("alt");
System.out.print(altvalue);
}
Related
If I have class like this:
class MyObject {
public int myInt;
public String myString;
}
Is it possible to convert instance of this class to HashMap without implementing converting code?
MyObject obj = new MyObject();
obj.myInt = 1; obj.myString = "string";
HashMap<String, Object> hs = convert(obj);
hs.getInt("myInt"); // returns 1
hs.getString("myString"); // returns "string"
Does Java provide that kind of solution, or I need to implement convert by myself?
My Class has more than 50 fields and writing converter for each field is not so good idea.
With jackson library this is also possible
MyObject obj = new MyObject();
obj.myInt = 1;
obj.myString = "1";
ObjectMapper mapObject = new ObjectMapper();
Map < String, Object > mapObj = mapObject.convertValue(obj, Map.class);
You can use reflection for implementing this behavior. You can get all fields of the class you want to convert to map iterate over this fields and take the name of each field as key of the map. This will result in a map from String to object.
Map<String, Object> myObjectAsDict = new HashMap<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
Class<?> targetType = field.getType();
Object objectValue = targetType.newInstance();
Object value = field.get(objectValue);
myObjectAsDict.put(field.getName(), value);
}
}
Something like that will do the trick:
MyObject obj = new MyObject();
obj.myInt = 1; obj.myString = "string";
Map<String, Object> map = new HashMap<>();
// Use MyObject.class.getFields() instead of getDeclaredFields()
// If you are interested in public fields only
for (Field field : MyObject.class.getDeclaredFields()) {
// Skip this if you intend to access to public fields only
if (!field.isAccessible()) {
field.setAccessible(true);
}
map.put(field.getName(), field.get(obj));
}
System.out.println(map);
Output:
{myString=string, myInt=1}
You might consider using a map instead of a class.
Or have your class extend a map such as
public class MyObject extends HashMap<String, Object> {
}
If you don't want to use Reflection then you can use my trick. hope this may help for someone.
Suppose your class looks like this.
public class MyClass {
private int id;
private String name;
}
Now Override toString() method in this class. in Eclipse there is a shortcut for generating this method also.
public class MyClass {
private int id;
private String name;
#Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("MyClass [id=").append(id).append(", name=").append(name).append("]");
return builder.toString();
}
}
Now write a method inside this class that will convert your object into Map<String,String>
public Map<String, String> asMap() {
Map<String, String> map = new HashMap<String, String>();
String stringRepresentation = this.toString();
if (stringRepresentation == null || stringRepresentation.trim().equals("")) {
return map;
}
if (stringRepresentation.contains("[")) {
int index = stringRepresentation.indexOf("[");
stringRepresentation = stringRepresentation.substring(index + 1, stringRepresentation.length());
}
if (stringRepresentation.endsWith("]")) {
stringRepresentation = stringRepresentation.substring(0, stringRepresentation.length() - 1);
}
String[] commaSeprated = stringRepresentation.split(",");
for (int i = 0; i < commaSeprated.length; i++) {
String keyEqualsValue = commaSeprated[i];
keyEqualsValue = keyEqualsValue.trim();
if (keyEqualsValue.equals("") || !keyEqualsValue.contains("=")) {
continue;
}
String[] keyValue = keyEqualsValue.split("=", 2);
if (keyValue.length > 1) {
map.put(keyValue[0].trim(), keyValue[1].trim());
}
}
return map;
}
Now from any where in your application you can simply call this method to get your HashMap from the Object. Cheers
Updated approach using reflection:
public static <T> Map<String, String> parseInnerClass(T classInstance) {
LinkedHashMap<String, String> ret = new LinkedHashMap<>();
for (Field attr : classInstance.getClass().getDeclaredFields()) {
String attrValue = "";
attr.setAccessible(true);
try {
attrValue = attr.get(classInstance).toString();
} catch (IllegalAccessException | NullPointerException e) {
// Do not add nothing
}
ret.put(attr.getName(), attrValue);
}
return ret;
}
I have a class
like below
public class SampleReflection {
public static final String TWO_name = "html";
public static final String TWO_find = "css";
public static final String ONE_KEY_java = "java";
public static final String ONE_KEY_jsp = "jsp";
public static final String ONE_KEY_oracle = "oracle";
public static final String ONE_KEY_spring = "spring";
public static final String ONE_KEY_struts = "struts";
}
I would like to get all the fields which starts with ONE_KEY and their value.
because the ONE_KEY_xxx can be of any numbers.
how to do this in java reflection or any other way in java ?
thanks
You can use SampleReflection.class.getDeclaredFields(), iterate over the result and filter by name. Then call field.get(null) to get the value of the static fields. If you want to access non-public fields as well you might have to call first.setAccessible(true) (provided the security manager allows that).
Alternatively you could have a look at Apache Common's reflection utilities, e.g. FieldUtils and the like.
Depending on what you actually want to achieve there might be better approaches though, e.g. using a map, enums etc.
In your case where you have static fields using an enum might be a better way to go.
Example:
enum SampleFields {
TWO_name("html"),
TWO_find("css"),
ONE_KEY_java("java"),
ONE_KEY_jsp("jsp");
ONE_KEY_oracle("oracle"),
...;
private String value;
private SampleFields(String v) {
value = v;
}
}
Then iterate over SampleFields.values() and filter by name.
Alternatively, if that fits your needs, you could split the names and pass a map to the enum values, e.g.
enum SampleFields {
TWO(/*build a map "name"->"html","find"->"css")*/ ),
ONE_KEY(/*build a map "java"->"java","jsp"->"jsp", ...*/);
private Map<String, String> values;
private SampleFields(Map<String, String> map) {
values = map;
}
}
Then get the enum values like this: SampleFields.valueOf("ONE_KEY").get("java")
Thanks for the answer,
this is what i was looking for,
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class SampleReflection {
public static final String TWO_name = "html";
public static final String TWO_find = "css";
public static final String ONE_KEY_java = "java";
public static final String ONE_KEY_jsp = "jsp";
public static final String ONE_KEY_oracle = "oracle";
public static final String ONE_KEY_spring = "spring";
public static final String ONE_KEY_struts = "struts";
public static void main(String[] args) {
Class<?> thisClass = null;
Map<String,String> keyValueMap = new HashMap<String,String>();
try {
thisClass = Class.forName(SampleReflection.class.getName());
Field[] aClassFields = thisClass.getDeclaredFields();
for(Field f : aClassFields){
String fName = f.getName();
if(fName.contains("ONE_KEY")){
keyValueMap.put(fName, (String)f.get(SampleReflection.class));
}
}
for (Map.Entry<String, String> entry : keyValueMap.entrySet())
{
System.out.println(entry.getKey() + "=" + entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
I want to use the method execute() of the following class:
public class Parser {
#Header("header1")
private String attribute1;
#Header("header2")
private String attribute2;
#Header("header3")
private String attribute3;
#Header("header4")
private String attribute4;
public String execute(String headerValue) {
//Execute
}
}
What I want this method to achieve is matching the headerValue parameter with one in the list of #Header annotations, and returning the value of the respective attribute. For example, if I call execute("header3"), it should return the value of attribute3
How can I achieve this? Or is it a better way to code this requirement?
Why don't you just use a map for this? You'd need one anyways in order to store the mapping of the annotation parameter value to the field but if you can do this without reflection it should be easier to code and to maintain.
What I mean is:
Map<String, String> attributes; //initialized
attributes.put("header1", value1);
...
In execute() you then just access the map.
You could improve this using an enum, e.g. in order to restrict the number of possible values.
Something like this:
enum HeaderType {
HEADER1,
HEADER2,
...
}
private Map<HeaderType, String> headerAttribs = ...;
void setAttrib( HeaderType type, String value ) {
headerAttribs.put(type, value);
}
String getAttrib( HeaderType type ) {
return headerAttribs.get(type);
}
public String execute(HeaderType type ) {
//Execute
}
If you need to use a string for the header type you could consider employing an additional map string->header type to look up the correct type first.
Alternatively you could use a switch statement which since Java 7 should work with strings as well.
Try this:
public String execute(String headerValue) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
for(Field field:this.getClass().getFields()) {
if (field.isAnnotationPresent(Header.class)) {
Header annotation = field.getAnnotation(Header.class);
String name = annotation.value();
if(name.equals(headerValue)) {
Object val = this.getClass().getField(name).get(this);
return (String) val;
}
}
}
return null;
}
There are a couple of exception to handle in line:
Object val = this.getClass().getField(name).get(this);
You can return null for that exception if you don't want to throw it from this method.
This may help you
Field f[]= Parser.class.getDeclaredFields();
for (int i = 0; i < f.length; i++) {
Annotation annotation[]= f[i].getAnnotations();
for (int j=0;j<annotation.length;j++){
Class<Annotation> type = (Class<Annotation>) annotation[j].annotationType();
for (Method method : type.getDeclaredMethods()) {
if(method.getName() .equals(headerValue))
{
String name=f[i].getName();
return name;
}
}
}
}
Parser.class.getDeclaredFields() will include private fields also.
I wanted to create a table/list in Java, and I wonder what is the best way to handle it.
The table should have a structure like this:
Term propertyList entitiesList
a1 p1=1, p2=2, p3=2 T1,T2
a2 p5=0, p4=5 ,p3=3 T2,T1
a3 p1=1 ,p4=3, p3=9 T3,T1,T2
...
a10
I have a list with exactly 10 terms, and for every term there is a list of properties (deep with key and value), and the properties can be either in one or more entities.
I need some help on how to create it, e.g. should I use list, map, collection etc.
How can I add hardcoded values to them as literals in the code, and what is the best way to read data from it, taking into account performance, given that later I will need to use this for every entity and find the related properties that participate in every term.
first off Create Term class.
So you have list of Terms: List<Term>
Term class
public class Term {
private String mName = "";
private Map<String, Integer> mPropertyMap = new LinkedHashMap<String, Integer>();
private List<String> mEntitiesList = new ArrayList<String>();
public Term(String name) {
mName = name;
}
public void generate(Map<String, Integer> propertyMap, List<String> entitiesList) {
mPropertyMap = propertyMap;
mEntitiesList = entitiesList;
}
public Map<String, Integer> getPropertyMap() {
return mPropertyMap;
}
public void setPropertyMap(Map<String, Integer> propertyMap) {
this.mPropertyMap = propertyMap;
}
public List<String> getEntitiesList() {
return mEntitiesList;
}
public void setEntitiesList(List<String> entitiesList) {
this.mEntitiesList = entitiesList;
}
public String getName() {
return mName;
}
public void setmName(String name) {
this.mName = name;
}
}
Main Class
public class MyClass {
private List<Term> mTermList = null;
private void init() {
mTermList = new ArrayList<Term>();
}
private void addSomeTerm() {
Map<String, Integer> propertyMap = new LinkedHashMap<String, Integer>();
propertyMap.put("p1", 1);
propertyMap.put("p2", 2);
propertyMap.put("p3", 3);
List<String> entitiesList = new ArrayList<String>();
entitiesList.add("T1");
entitiesList.add("T2");
Term term = new Term("a1");
term.generate(propertyMap, entitiesList);
mTermList.add(term);
}
private String printTerms() {
StringBuilder buff = new StringBuilder();
for(Term currTerm : mTermList){
buff.append(currTerm.getName()).append(" ");
Map<String, Integer> propertyMap = currTerm.getPropertyMap();
Set<String> sets = propertyMap.keySet();
Iterator<String> itr = sets.iterator();
String key = null;
Integer value = null;
while(itr.hasNext()){
key = itr.next();
value = propertyMap.get(key);
buff.append(key + "=" + value).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
buff.append(" ");
List<String> entitiesList = currTerm.getEntitiesList();
for(String str : entitiesList){
buff.append(str).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
}
return buff.toString();
}
/**
* #param args
*/
public static void main(String[] args) {
MyClass m = new MyClass();
m.init();
m.addSomeTerm();
System.out.println(m.printTerms());
}
}
Output:
a1 p1=1,p2=2,p3=3 T1,T2
It looks like you could have the following structure:
class Term {
String id;
Map<String, String> properties;
List<Entity> entities; // (or Set<Entity> if no duplicates are allowed)
}
But it's not very clear what you mean by "deep" and by "the properties can be either in one or more entities".
I have a ArrayList with custom objects. I want to search inside this ArrayList for Strings.
The class for the objects look like this:
public class Datapoint implements Serializable {
private String stateBased;
private String name;
private String priority;
private String mainNumber;
private String groupadress;
private String dptID;
public Datapoint(){
}
public String getMainNumber() {
return mainNumber;
}
public void setMainNumber(String mainNumber) {
this.mainNumber = mainNumber;
}
public String getName() {
return name;
}
..and so on
I know how to search for a string in a ArrayList but how to do that in a ArrayList with my custom objects:
ArrayList<String> searchList = new ArrayList<String>();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).contains(search)) {
//Do whatever you want here
}
}
So I want to have a function to search in my ArrayList with for example five objects for all "name" strings.
The easy way is to make a for where you verify if the atrrtibute name of the custom object have the desired string
for(Datapoint d : dataPointList){
if(d.getName() != null && d.getName().contains(search))
//something here
}
I think this helps you.
UPDATE: Using Java 8 Syntax
List<DataPoint> myList = new ArrayList<>();
//Fill up myList with your Data Points
List<DataPoint> dataPointsCalledJohn =
myList
.stream()
.filter(p-> p.getName().equals(("john")))
.collect(Collectors.toList());
If you don't mind using an external libaray - you can use Predicates from the Google Guava library as follows:
class DataPoint {
String name;
String getName() { return name; }
}
Predicate<DataPoint> nameEqualsTo(final String name) {
return new Predicate<DataPoint>() {
public boolean apply(DataPoint dataPoint) {
return dataPoint.getName().equals(name);
}
};
}
public void main(String[] args) throws Exception {
List<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
Collection<DataPoint> dataPointsCalledJohn =
Collections2.filter(myList, nameEqualsTo("john"));
}
try this
ArrayList<Datapoint > searchList = new ArrayList<Datapoint >();
String search = "a";
int searchListLength = searchList.size();
for (int i = 0; i < searchListLength; i++) {
if (searchList.get(i).getName().contains(search)) {
//Do whatever you want here
}
}
Probably something like:
ArrayList<DataPoint> myList = new ArrayList<DataPoint>();
//Fill up myList with your Data Points
//Traversal
for(DataPoint myPoint : myList) {
if(myPoint.getName() != null && myPoint.getName().equals("Michael Hoffmann")) {
//Process data do whatever you want
System.out.println("Found it!");
}
}
For a custom class to work properly in collections you'll have to implement/override the equals() methods of the class. For sorting also override compareTo().
See this article or google about how to implement those methods properly.
contains() method just calls equals() on ArrayList elements, so you can overload your class's equals() based on the name class variable. Return true from equals() if name is equal to the matching String. Hope this helps.
Use Apache CollectionUtils:
CollectionUtils.find(myList, new Predicate() {
public boolean evaluate(Object o) {
return name.equals(((MyClass) o).getName());
}
}
String string;
for (Datapoint d : dataPointList) {
Field[] fields = d.getFields();
for (Field f : fields) {
String value = (String) g.get(d);
if (value.equals(string)) {
//Do your stuff
}
}
}
boolean found;
for(CustomObject obj : ArrayOfCustObj) {
if(obj.getName.equals("Android")) {
found = true;
}
}