Java tutorial
/******************************************************************************* * QMetry Automation Framework provides a powerful and versatile platform to author * Automated Test Cases in Behavior Driven, Keyword Driven or Code Driven approach * * Copyright 2016 Infostretch Corporation * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE * * You should have received a copy of the GNU General Public License along with this program in the name of LICENSE.txt in the root folder of the distribution. If not, see https://opensource.org/licenses/gpl-3.0.html * * See the NOTICE.TXT file in root folder of this source files distribution * for additional information regarding copyright ownership and licenses * of other open source software / files used by QMetry Automation Framework. * * For any inquiry or need additional information, please contact support-qaf@infostretch.com *******************************************************************************/ package com.qmetry.qaf.automation.data; import static com.qmetry.qaf.automation.core.ConfigurationManager.getBundle; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.ParseException; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Random; import java.util.StringTokenizer; import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.RandomUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.json.JSONException; import org.json.JSONObject; import org.testng.SkipException; import com.qmetry.qaf.automation.keys.ApplicationProperties; import com.qmetry.qaf.automation.testng.RetryAnalyzer; import com.qmetry.qaf.automation.testng.pro.DataProviderUtil; import com.qmetry.qaf.automation.util.ClassUtil; import com.qmetry.qaf.automation.util.DatabaseUtil; import com.qmetry.qaf.automation.util.DateUtil; import com.qmetry.qaf.automation.util.JSONUtil; import com.qmetry.qaf.automation.util.Randomizer; import com.qmetry.qaf.automation.util.StringUtil; import com.qmetry.qaf.automation.util.RandomStringGenerator.RandomizerTypes; /** * com.qmetry.qaf.automation.data.BaseDataBean.java * * @author chirag */ public abstract class BaseDataBean implements DataBean { transient protected final Log logger = LogFactory.getLog(getClass()); public String toCSV() { StringBuffer sb = new StringBuffer(); Field[] flds = this.getClass().getDeclaredFields(); for (Field fld : flds) { try { fld.setAccessible(true); if (fld.getDeclaringClass().equals(this.getClass()) && (fld.get(this) != null)) { sb.append(fld.get(this).toString()); } sb.append(","); } catch (Exception e) { e.printStackTrace(); } } return sb.toString(); } @SuppressWarnings("unchecked") public void fillData(Object obj) { if (obj instanceof Map) { fillData((Map<String, String>) obj); return; } if (obj instanceof String) { String str = String.valueOf(obj); if (JSONUtil.isValidJsonString(str)) { fillFromJsonString(str); return; } if (str.startsWith("select")) { fillDataFromDB(str); return; } if (!getBundle().subset(str).isEmpty()) { fillFromConfig(str); return; } } throw new SkipException( "Unable to fill data with unknown object. It must be either Map or String: valid json / property key / sql statement." + obj); } /** * returns all fields including from super class */ protected Field[] getFields() { return ClassUtil.getAllFields(this.getClass(), BaseDataBean.class); } /** * fill bean from json data. * * @param jsonstr */ public void fillFromJsonString(String jsonstr) { try { JSONObject jsonObject = new JSONObject(jsonstr); String[] keys = JSONObject.getNames(jsonObject); for (String key : keys) { fillData(key, jsonObject.getString(key)); } } catch (JSONException e) { logger.error(e); } } /** * Can be used with xml configuration file or properties file * * @param datakey */ public void fillFromConfig(String datakey) { List<Object[]> set = DataProviderUtil.getDataSetAsMap(datakey); if (set.isEmpty()) { return; } int index = 0; if (set.size() > 1) { if (ApplicationProperties.BEAN_POPULATE_RANDOM.getBoolenVal(false)) { // get random index from 0 to size-1. index = RandomUtils.nextInt(set.size()); } else { // get next index, if index exceeds size then start with 0. int cindex = getBundle().getInt(RetryAnalyzer.RETRY_INVOCATION_COUNT, 0); index = cindex % set.size(); } } fillData(set.get(index)[0]); } @Override public String toString() { StringBuilder sb = new StringBuilder("["); Field[] flds = getFields(); for (Field fld : flds) { try { fld.setAccessible(true); if ((fld.get(this) != null)) { sb.append(fld.getName() + " : " + fld.get(this).toString()); sb.append(","); } } catch (Exception e) { e.printStackTrace(); } } sb.deleteCharAt(sb.length() - 1); if (sb.length() > 0) { sb.append("]"); } return sb.toString(); } public String toCSV(String csvNames) { if ((csvNames == null) || csvNames.equalsIgnoreCase("all") || csvNames.equalsIgnoreCase("*")) { return toCSV(); } StringBuffer sb = new StringBuffer(); StringTokenizer fldNames = new StringTokenizer(csvNames, ","); while (fldNames.hasMoreTokens()) { try { Field fld = this.getClass().getDeclaredField(fldNames.nextToken()); fld.setAccessible(true); if (fld.get(this) != null) { sb.append(fld.get(this).toString()); } sb.append(","); } catch (Exception e) { e.printStackTrace(); } } return sb.toString(); } public String getCSVLabel() { StringBuffer sb = new StringBuffer(); Field[] flds = this.getClass().getDeclaredFields(); for (Field fld : flds) { try { if (fld.getDeclaringClass().equals(this.getClass())) { sb.append(fld.getName()); sb.append(","); } } catch (Exception e) { logger.error(e); } } return sb.toString(); } /** * @param map * bean property name as key and value to set as value. For * example if bean property is "firstName" map should contain * entry with key "FIRSTNAME" (case insensitive) */ public void fillData(Map<String, String> map) { for (String key : map.keySet()) { fillData(key, String.valueOf(map.get(key))); } } /** * Column names in record returned by query must match bean property names. * If query returns multiple records then bean will filled with first * record. * * @param query * for example * <code>select col1 as beanprop1, col2 as beanprop2 ... * from table</code> */ @SuppressWarnings("unchecked") public void fillDataFromDB(String query) { fillData(((Map<String, String>) DatabaseUtil.getRecordDataAsMap(query)[0][0])); } /** * @param fieldName * case insensitive field name * @param value */ public void fillData(String fieldName, String value) { Field[] fields = getFields();// this.getClass().getDeclaredFields(); for (Field field2 : fields) { Field field = field2; if (field.getName().equalsIgnoreCase(fieldName)) { if (!(Modifier.isFinal(field.getModifiers()))) { setField(field, value); } return; } } } /** * This will fill random data except those properties which has skip=true in * {@link Randomizer} annotation. Use {@link Randomizer} annotation to * specify data value to be generated for specific property. * * @see Randomizer */ public void fillRandomData() { Field[] fields = getFields(); for (Field field : fields) { logger.debug("NAME :: " + field.getName()); if (!(Modifier.isFinal(field.getModifiers()))) { RandomizerTypes type = RandomizerTypes.MIXED; int len = 10; long min = 0, max = 0; String prefix = "", suffix = ""; String format = ""; String[] list = {}; Randomizer randomizer = field.getAnnotation(Randomizer.class); if (randomizer != null) { if (randomizer.skip()) { continue; } type = field.getType() == Date.class ? RandomizerTypes.DIGITS_ONLY : randomizer.type(); len = randomizer.length(); prefix = randomizer.prefix(); suffix = randomizer.suffix(); min = randomizer.minval(); max = min > randomizer.maxval() ? min : randomizer.maxval(); format = randomizer.format(); list = randomizer.dataset(); } else { // @Since 2.1.2 randomizer annotation is must for random // value // generation continue; } String str = ""; if ((list == null) || (list.length == 0)) { str = StringUtil.isBlank(format) ? RandomStringUtils.random(len, !type.equals(RandomizerTypes.DIGITS_ONLY), !type.equals(RandomizerTypes.LETTERS_ONLY)) : StringUtil.getRandomString(format); } else { str = getRandomValue(list); } try { // deal with IllegalAccessException field.setAccessible(true); Method setter = null; try { setter = this.getClass().getMethod("set" + StringUtil.getTitleCase(field.getName()), String.class); } catch (Exception e) { } if ((field.getType() == String.class) || (null != setter)) { if ((list == null) || (list.length == 0)) { if ((min == max) && (min == 0)) { str = StringUtil.isBlank(format) ? RandomStringUtils.random(len, !type.equals(RandomizerTypes.DIGITS_ONLY), !type.equals(RandomizerTypes.LETTERS_ONLY)) : StringUtil.getRandomString(format); } else { str = String.valueOf((int) (Math.random() * ((max - min) + 1)) + min); } } String rStr = prefix + str + suffix; if (null != setter) { setter.setAccessible(true); setter.invoke(this, rStr); } else { field.set(this, rStr); } } else { String rStr = ""; if ((min == max) && (min == 0)) { rStr = RandomStringUtils.random(len, false, true); } else { rStr = String.valueOf((int) (Math.random() * ((max - min) + 1)) + min); } if (field.getType() == Integer.TYPE) { field.setInt(this, Integer.parseInt(rStr)); } else if (field.getType() == Float.TYPE) { field.setFloat(this, Float.parseFloat(rStr)); } else if (field.getType() == Double.TYPE) { field.setDouble(this, Double.parseDouble(rStr)); } else if (field.getType() == Long.TYPE) { field.setLong(this, Long.parseLong(rStr)); } else if (field.getType() == Short.TYPE) { field.setShort(this, Short.parseShort(rStr)); } else if (field.getType() == Date.class) { logger.info("filling date " + rStr); int days = Integer.parseInt(rStr); field.set(this, DateUtil.getDate(days)); } else if (field.getType() == Boolean.TYPE) { field.setBoolean(this, RandomUtils.nextBoolean()); } } } catch (IllegalArgumentException e) { logger.error("Unable to fill random data in field " + field.getName(), e); } catch (IllegalAccessException e) { logger.error("Unable to Access " + field.getName(), e); } catch (InvocationTargetException e) { logger.error("Unable to Access setter for " + field.getName(), e); } } } } protected void setField(Field field, String val) { try { // deal with IllegalAccessException field.setAccessible(true); if (field.getType() == String.class) { field.set(this, val); } else { Method setter = null; try { setter = this.getClass().getMethod("set" + StringUtil.getTitleCase(field.getName()), String.class); } catch (Exception e) { } if (null != setter) { setter.setAccessible(true); setter.invoke(this, val); } else if (field.getType() == Integer.TYPE) { field.setInt(this, Integer.parseInt(val)); } else if (field.getType() == Float.TYPE) { field.setFloat(this, Float.parseFloat(val)); } else if (field.getType() == Double.TYPE) { field.setDouble(this, Double.parseDouble(val)); } else if (field.getType() == Long.TYPE) { field.setLong(this, Long.parseLong(val)); } else if (field.getType() == Boolean.TYPE) { Boolean bval = StringUtils.isBlank(val) ? null : NumberUtils.isNumber(val) ? (Integer.parseInt(val) != 0) : Boolean.parseBoolean(val) || val.equalsIgnoreCase("T") || val.equalsIgnoreCase("Y") || val.equalsIgnoreCase("YES"); field.setBoolean(this, bval); } else if (field.getType() == Short.TYPE) { field.setShort(this, Short.parseShort(val)); } else if (field.getType() == Date.class) { Date dVal = null; try { dVal = StringUtils.isBlank(val) ? null : NumberUtils.isNumber(val) ? DateUtil.getDate(Integer.parseInt(val)) : DateUtil.parseDate(val, "MM/dd/yyyy"); } catch (ParseException e) { logger.error("Expected date in MM/dd/yyyy format.", e); } field.set(this, dVal); } } } catch (IllegalArgumentException e) { logger.error("Unable to fill random data in field " + field.getName(), e); } catch (IllegalAccessException e) { logger.error("Unable to Access " + field.getName(), e); } catch (InvocationTargetException e) { logger.error("Unable to invoke setter for " + field.getName(), e); } } public static String getRandomValue(String... values) { if ((values == null) || (values.length == 0)) { return ""; } if ((values.length == 1) && getBundle().containsKey(values[0])) { values = getBundle().getStringArray(values[0], values[0]); } Random rand = new Random(); int r = rand.nextInt(values.length); return values[r]; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } @SuppressWarnings("unchecked") public <T extends BaseDataBean> T deepClone() { try { // Serialization of object ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(this); // De-serialization of object ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream in = new ObjectInputStream(bis); T copied = (T) in.readObject(); return copied; } catch (Exception e) { throw new RuntimeException(e); } } }