/* This file is part of SlumDroid <https://github.com/slumdroid/slumdroid>. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 * as published by the Free Software Foundation. * * 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 <http://www.gnu.org/licenses/gpl-3.0.txt> * for more details. * * Copyright (C) 2012-2016 Gennaro Imparato */ package it.slumdroid.tool.components.abstractor; import static it.slumdroid.droidmodels.model.SimpleType.EXPAND_MENU; import static it.slumdroid.droidmodels.model.SimpleType.EXPAND_MENU_ITEM; import static it.slumdroid.droidmodels.model.SimpleType.TEXT_VIEW; import static it.slumdroid.droidmodels.model.SimpleType.TOAST; import static it.slumdroid.tool.components.abstractor.AbstractorUtilities.detectName; import static it.slumdroid.tool.components.abstractor.AbstractorUtilities.getType; import static it.slumdroid.tool.components.abstractor.AbstractorUtilities.setCount; import static it.slumdroid.tool.components.abstractor.AbstractorUtilities.setValue; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.DOMException; import org.w3c.dom.Element; import android.view.View; import android.widget.TextView; import it.slumdroid.droidmodels.guitree.FinalActivity; import it.slumdroid.droidmodels.guitree.GuiTree; import it.slumdroid.droidmodels.guitree.StartActivity; import it.slumdroid.droidmodels.model.ActivityState; import it.slumdroid.droidmodels.model.Task; import it.slumdroid.droidmodels.model.Transition; import it.slumdroid.droidmodels.model.UserEvent; import it.slumdroid.droidmodels.model.UserInput; import it.slumdroid.droidmodels.model.WidgetState; import it.slumdroid.droidmodels.model.WidgetType; import it.slumdroid.droidmodels.testcase.TestCaseActivity; import it.slumdroid.droidmodels.testcase.TestCaseEvent; import it.slumdroid.droidmodels.testcase.TestCaseInput; import it.slumdroid.droidmodels.testcase.TestCaseTask; import it.slumdroid.droidmodels.testcase.TestCaseTransition; import it.slumdroid.droidmodels.testcase.TestCaseWidget; import it.slumdroid.droidmodels.xml.ElementWrapper; import it.slumdroid.tool.components.persistence.PersistenceFactory; import it.slumdroid.tool.model.ActivityDescription; import it.slumdroid.tool.model.SaveStateListener; import it.slumdroid.tool.utilities.AllPassFilter; import it.slumdroid.tool.utilities.SessionParams; // TODO: Auto-generated Javadoc /** * The Class Abstractor. */ public class Abstractor implements SaveStateListener { /** The session. */ private GuiTree theSession; /** The base activity. */ private StartActivity baseActivity; /** The filters. */ private HashSet<AllPassFilter> filters = new HashSet<AllPassFilter>(); /** The detector. */ private TypeDetector detector = new TypeDetector(); /** The event id. */ private int eventId = 0; /** The input id. */ private int inputId = 0; /** The activity id. */ private int activityId = 0; /** The Constant ACTOR_NAME. */ public final static String ACTOR_NAME = "GuiTreeAbstractor"; /** The Constant EVENT_PARAM_NAME. */ private static final String EVENT_PARAM_NAME = "eventId"; /** The Constant INPUT_PARAM_NAME. */ private static final String INPUT_PARAM_NAME = "inputId"; /** The Constant ACTIVITY_PARAM_NAME. */ private static final String ACTIVITY_PARAM_NAME = "activityId"; /** * Instantiates a new gui tree abstractor. * * @throws ParserConfigurationException the parser configuration exception */ public Abstractor() throws ParserConfigurationException { setTheSession(new GuiTree()); PersistenceFactory.registerForSavingState(this); } /** * Gets the the session. * * @return the the session */ public GuiTree getTheSession() { return this.theSession; } /** * Sets the the session. * * @param theSession the new the session */ public void setTheSession(GuiTree theSession) { this.theSession = theSession; } /** * Gets the type detector. * * @return the type detector */ public TypeDetector getTypeDetector() { return this.detector; } /** * Creates the activity. * * @param theDescription the the description * @return the activity state */ public ActivityState createActivity(ActivityDescription theDescription) { return createActivity(theDescription, false); } // If the boolean parameter is omitted, the overloading method will default to a Final Activity /** * Creates the activity. * * @param theDescription the description * @param start the start * @return the activity state */ public ActivityState createActivity(ActivityDescription theDescription, boolean start) { ActivityState newActivity = (start)?StartActivity.createActivity(getTheSession()):FinalActivity.createActivity(getTheSession()); for (AllPassFilter filter: this.filters) { filter.clear(); } boolean hasDescription = updateDescription(newActivity, theDescription); if (!hasDescription) { newActivity.markAsExit(); newActivity.setUniqueId(getUniqueActivityId()); return newActivity; } newActivity.setName(theDescription.getActivityName()); newActivity.setTitle(theDescription.getActivityTitle()); newActivity.setUniqueId(getUniqueActivityId()); newActivity.setId(newActivity.getUniqueId()); return newActivity; } /** * Creates the widget. * * @param view the view * @return the test case widget */ public TestCaseWidget createWidget(View view) { TestCaseWidget widget = TestCaseWidget.createWidget(getTheSession()); String id = String.valueOf(view.getId()); String name = detectName(view); widget.setIdNameType(id, name, getType(view)); widget.setSimpleType(getTypeDetector().getSimpleType(view)); setCount(view, widget); setValue(view, widget); if (view instanceof TextView) { int type = ((TextView)view).getInputType(); if (type != 0) { widget.setTextType(new WidgetType(type, name, widget.getValue()).convert()); } } widget.setAvailable((view.isEnabled())?"true":"false"); widget.setClickable((view.isClickable())?"true":"false"); widget.setLongClickable((view.isLongClickable())?"true":"false"); return widget; } /** * Update description. * * @param newActivity the new activity * @param theDescription the description * @return true, if successful */ public boolean updateDescription(ActivityState newActivity, ActivityDescription theDescription) { boolean hasDescription = false; boolean hasMenuList = false; int countMenuList = 0; for (View view: theDescription) { hasDescription = true; if (!view.isShown()) { continue; } TestCaseWidget widget = createWidget(view); widget.setIndex(theDescription.getWidgetIndex(view)); if (widget.getIndex() == 0 && widget.getSimpleType().equals(TEXT_VIEW)) { widget.setSimpleType(TOAST); } if (widget.getSimpleType().equals(EXPAND_MENU)) { countMenuList = widget.getCount(); hasMenuList = true; } if (hasMenuList && countMenuList != 0) { if (!widget.getId().equals("-1")) { if (widget.getSimpleType().equals(TEXT_VIEW)) { widget.setSimpleType(EXPAND_MENU_ITEM); countMenuList--; } } } ((ElementWrapper) newActivity).appendChild(widget.getElement()); for (AllPassFilter filter: this.filters) { filter.loadItem(widget); } } return hasDescription; } /** * Sets the base activity. * * @param theDescription the new base activity */ /* (non-Javadoc) * @see it.slumdroid.tool.model.Abstractor#setBaseActivity(it.slumdroid.tool.model.ActivityDescription) */ public void setBaseActivity(ActivityDescription theDescription) { this.baseActivity = (StartActivity) createActivity(theDescription, true); } /** * Gets the base activity. * * @return the base activity */ public ActivityState getBaseActivity() { return this.baseActivity; } /** * Sets the start activity. * * @param theStep the the step * @param theActivity the the activity */ public void setStartActivity(Transition theStep, ActivityState theActivity) { theStep.setStartActivity(stubActivity(theActivity)); } /** * Sets the final activity. * * @param theTask the the task * @param theActivity the the activity */ public void setFinalActivity(Task theTask, ActivityState theActivity) { theTask.setFinalActivity(stubActivity(theActivity)); } /** * Stub activity. * * @param theActivity the the activity * @return the test case activity */ private TestCaseActivity stubActivity(ActivityState theActivity) { TestCaseActivity theStub = ((TestCaseActivity)theActivity).clone(); return theStub; } /** * Iterator. * * @return the iterator */ public Iterator<AllPassFilter> iterator() { return this.filters.iterator(); } /** * Adds the filter. * * @param filter the filter */ public void addFilter(AllPassFilter filter) { this.filters.add(filter); } /** * Creates the event. * * @param target the target * @param type the type * @return the user event */ public UserEvent createEvent(WidgetState target, String type) { TestCaseEvent newEvent = TestCaseEvent.createEvent(getTheSession()); if (target != null) { newEvent.setWidget(target.clone()); } newEvent.setType(type); newEvent.setId(getUniqueEventId()); return newEvent; } /** * Creates the event. * * @param type the type * @return the user event */ public UserEvent createEvent(String type) { TestCaseEvent newEvent = TestCaseEvent.createEvent(getTheSession()); newEvent.setType(type); newEvent.setId(getUniqueEventId()); return newEvent; } /** * Creates the input. * * @param target the target * @param value the value * @param type the type * @return the user input */ public UserInput createInput(WidgetState target, String value, String type) { TestCaseInput newInput = TestCaseInput.createInput(getTheSession()); newInput.setWidget(target.clone()); newInput.setValue(value); newInput.setType(type); newInput.setId(getUniqueInputId()); return newInput; } /** * Creates the task. * * @param head the head * @param tail the tail * @return the task */ public Task createTask(Task head, Transition tail) { TestCaseTask task; if (head != null) { task = ((TestCaseTask)head).clone(); } else { task = new TestCaseTask(getTheSession()); } task.addTransition(tail); return task; } /** * Import task. * * @param fromXml the from xml * @return the task */ public Task importTask(Element fromXml) { TestCaseTask imported = new TestCaseTask(getTheSession()); Element task = (Element)getTheSession().getDom().adoptNode(fromXml); imported.setElement(task); return imported; } /** * Import state. * * @param fromXml the from xml * @return the activity state */ public ActivityState importState(Element fromXml) { return getTheSession().importState(fromXml); } /** * Creates the transition. * * @param start the start * @param event the event * @return the transition */ public Transition createTransition(ActivityState start, UserEvent event) { Transition transition = TestCaseTransition.createTransition(start.getElement().getOwnerDocument()); try { setStartActivity(transition, StartActivity.createActivity(start)); transition.setEvent(event); } catch (DOMException e) { e.printStackTrace(); } return transition; } /** * Creates the transition. * * @param start the start * @param inputs the inputs * @param event the event * @return the transition */ public Transition createTransition(ActivityState start, Collection<UserInput> inputs, UserEvent event) { Transition transition = TestCaseTransition.createTransition(start.getElement().getOwnerDocument()); try { setStartActivity(transition, StartActivity.createActivity(start)); for (UserInput inPut: inputs) { transition.addInput(inPut); } transition.setEvent(event); } catch (DOMException e) { e.printStackTrace(); } return transition; } /** * Gets the unique event id. * * @return the unique event id */ public String getUniqueEventId() { int ret = this.eventId; this.eventId++; return "e" + ret; } /** * Gets the unique activity id. * * @return the unique activity id */ public String getUniqueActivityId() { int ret = this.activityId; this.activityId++; return "a" + ret; } /** * Gets the unique input id. * * @return the unique input id */ public String getUniqueInputId() { int ret = this.inputId; this.inputId++; return "i" + ret; } /* (non-Javadoc) * @see it.slumdroid.tool.model.SaveStateListener#onSavingState() */ public SessionParams onSavingState() { SessionParams state = new SessionParams(); state.store(EVENT_PARAM_NAME, this.eventId); state.store(INPUT_PARAM_NAME, this.inputId); state.store(ACTIVITY_PARAM_NAME, this.activityId); return state; } /* (non-Javadoc) * @see it.slumdroid.tool.model.SaveStateListener#onLoadingState(it.slumdroid.tool.utilities.SessionParams) */ public void onLoadingState(SessionParams sessionParams) { this.eventId = sessionParams.getInt(EVENT_PARAM_NAME); this.inputId = sessionParams.getInt(INPUT_PARAM_NAME); this.activityId = sessionParams.getInt(ACTIVITY_PARAM_NAME); } /* (non-Javadoc) * @see it.slumdroid.tool.model.SaveStateListener#getListenerName() */ public String getListenerName() { return ACTOR_NAME; } }