All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ats.executor.drivers.desktop.SystemDriver Maven / Gradle / Ivy

The newest version!
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
 */

package com.ats.executor.drivers.desktop;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import com.ats.AtsSingleton;
import com.ats.data.Dimension;
import com.ats.data.Point;
import com.ats.data.Rectangle;
import com.ats.driver.AtsRemoteWebDriver;
import com.ats.element.AtsBaseElement;
import com.ats.element.FoundElement;
import com.ats.element.JsonUtils;
import com.ats.element.test.TestElement;
import com.ats.executor.ActionStatus;
import com.ats.executor.ActionTestScript;
import com.ats.executor.ScriptStatus;
import com.ats.executor.TestBound;
import com.ats.executor.channels.Channel;
import com.ats.executor.drivers.DriverInfo;
import com.ats.executor.drivers.IDriverInfo;
import com.ats.executor.drivers.RemoteDriverInfo;
import com.ats.executor.drivers.engines.SystemDriverEngine;
import com.ats.generator.objects.MouseDirectionData;
import com.ats.generator.variables.CalculatedProperty;
import com.ats.recorder.RecorderSummaryData;
import com.ats.recorder.TestSummary;
import com.ats.script.ScriptHeader;
import com.ats.tools.OperatingSystem;
import com.ats.tools.Utils;
import com.ats.tools.logger.ExecutionLogger;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.gson.Gson;

import okhttp3.OkHttpClient;
import okhttp3.OkHttpClient.Builder;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

public class SystemDriver extends AtsRemoteWebDriver {

	private static final int TIME_OUT = 600;
		
	private static final String MS_EDGE_PATH = "MsEdgePath";

	private static final String ATS_CLIENT_ID = "Ats-Client-Id";
	private static final String ERROR_ATS_DESKTOP_RESPONSE = "ErrorAtsDesktopResponse";

	private List elementMapLocation;

	private IDriverInfo systemDriverInfo;
	private SystemDriverEngine engine;

	private OkHttpClient client;

	private String driverVersion;
	private String osName;
	private String osVersion;
	private String osBuildVersion;

	private String countryCode;
	private String machineName;
	private String screenWidth;
	private String screenHeight;
	private String driveLetter;

	private String diskTotalSize;
	private String diskFreeSpace;

	private String cpuArchitecture;
	private String cpuCores;
	private String cpuName;
	private String cpuSocket;
	private String cpuMaxClock;

	private String dotNetVersion;
	private String userHome;
	private boolean interactive = true;
	
	private Map capabilities = new HashMap();

	@SuppressWarnings("unused")
	private String logFile;//TODO show this file path to user

	private final ObjectMapper mapper = new ObjectMapper();

	public SystemDriver() {}

	public SystemDriver(ActionStatus status, ActionTestScript script) {

		if("true".equals(System.getProperty("ats.dev"))){
			setDevTimeout();
		}else {
			setNormalTimeout();
		}

		systemDriverInfo = AtsSingleton.getInstance().getSystemDriver(status, script);

		if(status.isPassed()) {
			
			//multi-try to get session if driver not ready
			JsonNode sessionNode = sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_SESSION.getPath());
			if(!sessionNode.has("capabilities")) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {}
				sessionNode = sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_SESSION.getPath());
			}

			if(sessionNode.has("capabilities")) {

				final Iterator> fields = sessionNode.get("capabilities").fields();

				while(fields.hasNext()) {
					final Entry cap = fields.next();

					if("BuildNumber".equals(cap.getKey())) {
						this.osBuildVersion = cap.getValue().asText();
					}else if("Name".equals(cap.getKey())) {
						this.osName = cap.getValue().asText();
					}else if("Version".equals(cap.getKey())) {
						this.osVersion = cap.getValue().asText();
					}else if("DriverVersion".equals(cap.getKey())) {
						this.driverVersion = cap.getValue().asText();
					}else if("CountryCode".equals(cap.getKey())) {
						this.countryCode = cap.getValue().asText();
					}else if("MachineName".equals(cap.getKey())) {
						this.machineName = cap.getValue().asText();
					}else if("ScreenWidth".equals(cap.getKey())) {
						this.screenWidth = cap.getValue().asText();
					}else if("ScreenHeight".equals(cap.getKey())) {
						this.screenHeight= cap.getValue().asText();
					}else if("DriveLetter".equals(cap.getKey())) {
						this.driveLetter = cap.getValue().asText();
					}else if("DiskTotalSize".equals(cap.getKey())) {
						this.diskTotalSize = cap.getValue().asText();
					}else if("DiskFreeSpace".equals(cap.getKey())) {
						this.diskFreeSpace = cap.getValue().asText();
					}else if("CpuSocket".equals(cap.getKey())) {
						this.cpuSocket = cap.getValue().asText();
					}else if("CpuName".equals(cap.getKey())) {
						this.cpuName = cap.getValue().asText();
					}else if("CpuArchitecture".equals(cap.getKey())) {
						this.cpuArchitecture = cap.getValue().asText();
					}else if("CpuMaxClockSpeed".equals(cap.getKey())) {
						this.cpuMaxClock = cap.getValue().asText();
					}else if("CpuCores".equals(cap.getKey())) {
						this.cpuCores = cap.getValue().asText();
					}else if("DotNetVersion".equals(cap.getKey())) {
						this.dotNetVersion = cap.getValue().asText();
					}else if("UserHome".equals(cap.getKey())) {
						this.userHome = cap.getValue().asText();
					}else if("Interactive".equals(cap.getKey())) {
						this.interactive = !"false".equalsIgnoreCase(cap.getValue().asText());
					}else if("LogFile".equals(cap.getKey())) {
						this.logFile = cap.getValue().asText();
					}else {
						capabilities.put(cap.getKey(), cap.getValue().asText());
					}
				}

			}else {
				if(sessionNode.has("error")){
					status.setError(ActionStatus.CHANNEL_START_ERROR, sessionNode);
				}else {
					status.setError(ActionStatus.CHANNEL_START_ERROR, "unable to get system driver capabilities\ncheck SystemDriver is launched, DotNET and OS version ...");
				}
			}

		}else {
			status.setError(ActionStatus.CHANNEL_START_ERROR, "unable to connect to system driver\ncheck SystemDriver is launched, DotNET and OS version ...");
		}
	}

	public boolean isInteractive() {
		return interactive;
	}

	public String getOsType() {
		return OperatingSystem.getType(osName);
	}

	public byte[] getIcon() {
		return OperatingSystem.getIcon(getOsType());
	}

	public boolean isEnabled() {
		return engine != null ;
	}
	
	public boolean isLinux() {
		return OperatingSystem.isLinux(getOsName());
	}
	
	public String getMsEdgePath() {
		return capabilities.get(MS_EDGE_PATH);
	}

	/*private boolean isReady(ActionStatus status) {

		int maxTry = 20;

		JsonNode statusNode = sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_STATUS.getPath());
		while(maxTry > 0 && !statusNode.has("ready")) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {}

			statusNode = sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_STATUS.getPath());
			maxTry--;
		}

		if(statusNode.has("ready") && statusNode.get("ready").asBoolean()){
			return true;
		}else {
			status.setError(ActionStatus.CHANNEL_START_ERROR, statusNode);
			return false;
		}
	}*/

	private void setTimeout(int to) {
		this.client = new Builder().cache(null)
				.connectTimeout(to, TimeUnit.SECONDS)
				.writeTimeout(to, TimeUnit.SECONDS)
				.readTimeout(to, TimeUnit.SECONDS)
				.build();
	}

	public void setNormalTimeout() {
		setTimeout(TIME_OUT);
	}

	public void setExtendedTimeout() {
		setTimeout(2*TIME_OUT);
	}

	private void setDevTimeout() {
		setTimeout(1000*TIME_OUT);
	}

	private void setDownloadTimeout() {
		setTimeout(60*TIME_OUT);
	}

	public Double getScreenWidth() {
		try {
			return Double.parseDouble(screenWidth);
		}catch(NumberFormatException e) {}
		return 0D;
	}

	public Double getScreenHeight() {
		try {
			return Double.parseDouble(screenHeight);
		}catch(NumberFormatException e) {}
		return 0D;
	}

	public TestBound getScreenBound() {
		return new TestBound(0D, 0D, getScreenWidth(), getScreenHeight());
	}

	public void setEngine(SystemDriverEngine engine) {
		this.engine = engine;
		engine.setDriver(this);
	}

	public SystemDriverEngine getEngine() {
		return engine;
	}

	public String getDriverVersion() {
		return driverVersion;
	}

	public String getUserHome() {
		return userHome;
	}

	public String getOsFullName() {
		return getOsName() + " (" + getOsVersion() + ")";
	}

	public String getOsBuildVersion() {
		return osBuildVersion;
	}

	public String getOsName() {
		return osName;
	}

	public String getOsVersion() {
		return osVersion;
	}

	public String getCountryCode() {
		return countryCode;
	}

	public String getMachineName() {
		return machineName;
	}

	public String getScreenResolution() {
		return screenWidth + " x " + screenHeight;
	}

	public String getDriveLetter() {
		return driveLetter;
	}

	public String getDiskTotalSize() {
		return diskTotalSize;
	}

	public String getDiskFreeSpace() {
		return diskFreeSpace;
	}

	public String getCpuArchitecture() {
		return cpuArchitecture;
	}

	public String getCpuCores() {
		return cpuCores;
	}

	public String getCpuName() {
		return cpuName;
	}

	public String getCpuSocket() {
		return cpuSocket;
	}

	public String getCpuMaxClock() {
		return cpuMaxClock;
	}

	public String getDotNetVersion() {
		return dotNetVersion;
	}

	//------------------------------------------------------------------------------------------------------------
	// New Enum types
	//------------------------------------------------------------------------------------------------------------

	public enum HttpMethod
	{
		GET ("GET"),
		POST ("POST"),
		DELETE ("DELETE");

		private final String type;
		HttpMethod(String value){
			this.type = value;
		}

		@Override
		public String toString(){ return this.type; }
	}

	/**
	 * Api road for the system driver
	 */
	public enum ApiRoute {
		DRIVER_CAPABILITIES(new String[] {"session", "SESSION_ID" ,"ats", "driver", "capabilities"}),
		DRIVER_REMOTE_DRIVER(new String[] {"session", "SESSION_ID" ,"ats", "driver", "remoteDriver"}),
		DRIVER_APPLICATION(new String[] {"session", "SESSION_ID" ,"ats", "driver", "application"}),
		DRIVER_CLOSE_WINDOWS(new String[] {"session", "SESSION_ID" ,"ats", "driver", "closeWindows"}),
		DRIVER_CLOSE(new String[] {"session", "SESSION_ID" ,"ats", "driver", "close"}),
		DRIVER_OSTRACON(new String[] {"session", "SESSION_ID" ,"ats", "driver", "ostracon"}),
		DRIVER_SHAPES(new String[] {"session", "SESSION_ID" ,"ats", "driver", "shapes"}),
		MOUSE_MOVE(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "move"}),
		MOUSE_CLICK(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "click"}),
		MOUSE_RIGHT_CLICK(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "rightClick"}),
		MOUSE_MIDDLE_CLICK(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "middleClick"}),
		MOUSE_DOUBLE_CLICK(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "doubleClick"}),
		MOUSE_DOWN(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "down"}),
		MOUSE_RELEASE(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "release"}),
		MOUSE_WHEEL(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "wheel"}),
		MOUSE_DRAG(new String[] {"session", "SESSION_ID" ,"ats", "mouse", "drag"}),
		KEY_CLEAR(new String[] {"session", "SESSION_ID" ,"ats", "keyboard", "clear"}),
		KEY_ENTER(new String[] {"session", "SESSION_ID" ,"ats", "keyboard", "enter"}),
		KEY_DOWN(new String[] {"session", "SESSION_ID" ,"ats", "keyboard", "down"}),
		KEY_RELEASE(new String[] {"session", "SESSION_ID" ,"ats", "keyboard", "release"}),
		RECORDER_STOP(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "stop"}),
		RECORDER_SCREENSHOT(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "screenShot"}),
		RECORDER_START(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "start"}),
		RECORDER_CREATE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "create"}),
		RECORDER_IMAGE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "image"}),
		RECORDER_VALUE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "value"}),
		RECORDER_DATA(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "data"}),
		RECORDER_STATUS(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "status"}),
		RECORDER_ELEMENT(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "element"}),
		RECORDER_POSITION(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "position"}),
		RECORDER_DOWNLOAD(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "download"}),
		RECORDER_IMAGE_MOBILE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "imageMobile"}),
		RECORDER_CREATE_MOBILE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "createMobile"}),
		RECORDER_SCREENSHOT_MOBILE(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "screenShotMobile"}),
		RECORDER_SUMMARY(new String[] {"session", "SESSION_ID" ,"ats", "recorder", "summary"}),
		WINDOW_TITLE(new String[] {"session", "SESSION_ID" , "ats", "window", "title"}),
		WINDOW_HANDLE(new String[] {"session", "SESSION_ID" ,"ats", "window", "handle"}),
		WINDOW_LIST(new String[] {"session", "SESSION_ID" ,"ats", "window", "list"}),
		WINDOW_MOVE(new String[] {"session", "SESSION_ID" ,"ats", "window", "move"}),
		WINDOW_RESIZE(new String[] {"session", "SESSION_ID" ,"ats", "window", "resize"}),
		WINDOW_TO_FRONT(new String[] {"session", "SESSION_ID" ,"ats", "window", "toFront"}),
		WINDOW_SWITCH(new String[] {"session", "SESSION_ID" ,"ats", "window", "switch"}),
		WINDOW_CLOSE(new String[] {"session", "SESSION_ID" ,"ats", "window", "close"}),
		WINDOW_URL(new String[] {"session", "SESSION_ID" ,"ats", "window", "url"}),
		WINDOW_KEYS(new String[] {"session", "SESSION_ID" ,"ats", "window", "keys"}),
		WINDOW_STATE(new String[] {"session", "SESSION_ID" ,"ats", "window", "state"}),
		WINDOW_CLOSE_WINDOW(new String[] {"session", "SESSION_ID" ,"ats", "window", "closeWindow"}),
		WINDOW_CLOSE_MODAL_WINDOWS(new String[] {"session", "SESSION_ID" ,"ats", "window", "closeModalWindows"}),
		ELEMENT_CHILDS(new String[] {"session", "SESSION_ID" ,"ats", "element", "childs"}),
		ELEMENT_PARENTS(new String[] {"session", "SESSION_ID" ,"ats", "element", "parents"}),
		ELEMENT_FIND(new String[] {"session", "SESSION_ID" ,"ats", "element", "find"}),
		ELEMENT_ATTRIBUTES(new String[] {"session", "SESSION_ID" ,"ats", "element", "attributes"}),
		ELEMENT_SELECT(new String[] {"session", "SESSION_ID" ,"ats", "element", "select"}),
		ELEMENT_FROM_POINT(new String[] {"session", "SESSION_ID" ,"ats", "element", "fromPoint"}),
		ELEMENT_SCRIPT(new String[] {"session", "SESSION_ID" ,"ats", "element", "script"}),
		ELEMENT_ROOT(new String[] {"session", "SESSION_ID" ,"ats", "element", "root"}),
		ELEMENT_LOAD_TREE(new String[] {"session", "SESSION_ID" ,"ats", "element", "loadTree"}),
		ELEMENT_LIST_ITEMS(new String[] {"session", "SESSION_ID" ,"ats", "element", "listItems"}),
		ELEMENT_DIALOG_BOX(new String[] {"session", "SESSION_ID" ,"ats", "element", "dialogBox"}),
		ELEMENT_FOCUS(new String[] {"session", "SESSION_ID" ,"ats", "element", "focus"}),
		ELEMENT_CONTEXT_MENU(new String[] {"session", "SESSION_ID" ,"ats", "element", "contextMenu"}),
		ATS_STATUS(new String[] {"status"}),
		ATS_PROFILE(new String[] {"profile"}),
		ATS_EXPLORER(new String[] {"explorer"}),
		ATS_SESSION(new String[] {"session"}),
		ATS_WINDOW(new String[] {"window", "title"})
		;

		private final String[] m_roadPath;

		ApiRoute(String[] path) { this.m_roadPath = path;	}

		public String[] getPath() { return this.getPath("1234567890");}
		public String[] getPath(String sessionId) {
			return Arrays.stream(this.m_roadPath).map(s -> "SESSION_ID".equals(s) ? sessionId : s).toArray(String[]::new);
		}
	}

	//------------------------------------------------------------------------------------------------------------
	//------------------------------------------------------------------------------------------------------------

	public StringBuilder getDriverHostAndPort() {
		return systemDriverInfo.getDriverHostAndPort();
	}

	public StringBuilder getLocalhostAndPort() {
		return new StringBuilder("http://localhost:").append(systemDriverInfo.getDriverServerUri().getPort());
	}

	public RemoteDriverInfo getRemoteDriver(ActionStatus status, String driverName, String appPath) {

		Map valueNode = new HashMap<>();
		valueNode.put("ats", true);
		valueNode.put("remoteDriver", driverName);
		valueNode.put("operatingSystem", OperatingSystem.getOS());
		valueNode.put("applicationPath", appPath);
		final JsonNode remoteDriver = sendRequestCommand(HttpMethod.POST,JsonUtils.createPostData(valueNode), ApiRoute.ATS_SESSION.getPath());

		if(remoteDriver.has(DriverInfo.SESSION_ID)) {
			final String driverId = remoteDriver.get(DriverInfo.SESSION_ID).asText();
			final JsonNode capabilities = remoteDriver.get("capabilities");
			if(capabilities.has("driverUrl")) {
				return new RemoteDriverInfo(driverId, systemDriverInfo.getDriverServerUri().getHost(), capabilities);
			}
		}else if(remoteDriver.has("error")) {
			status.setError(ActionStatus.DRIVER_NOT_REACHABLE, remoteDriver);
		}

		return null;
	}

	public String getDriverHost() {
		return systemDriverInfo.getDriverServerUri().getHost();
	}

	public int getDriverPort() {
		return systemDriverInfo.getDriverServerUri().getPort();
	}

	public void closeDriver() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.DRIVER_CLOSE.getPath());
		//		sendRequestCommandVoid(CommandType.Driver, DriverType.Close);
	}

	public void closeWindows(long processId, int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("processId", processId);
		valueNode.put("handle",handle );

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.DRIVER_CLOSE_WINDOWS.getPath());
	}

	public void clearText() {
		Map valueNode = new HashMap<>();
		valueNode.put("id", null);
		
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.KEY_CLEAR.getPath());
	}

	public void clearText(String elemId) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", elemId);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.KEY_CLEAR.getPath());
	}

	public void sendKeys(String data, String elemId) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", elemId);
		valueNode.put("data", data);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.KEY_ENTER.getPath());
	}
	public void keyDown(int codePoint) {
		Map valueNode = new HashMap<>();
		valueNode.put("codePoint", codePoint);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.KEY_DOWN.getPath());
	}

	public void keyUp(int codePoint) {
		Map valueNode = new HashMap<>();
		valueNode.put("codePoint", codePoint);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.KEY_RELEASE.getPath());
	}

	public void mouseMove(double x, double y) {
		Map valueNode = new HashMap<>();
		valueNode.put("x", (int)x);
		valueNode.put("y", (int)y);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_MOVE.getPath());
	}

	public void mouseClick() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_CLICK.getPath());
	}

	public void mouseClick(int key) {
		Map valueNode = new HashMap<>();
		valueNode.put("key", key);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_CLICK.getPath());
	}

	public void mouseRightClick() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_RIGHT_CLICK.getPath());
	}

	public void mouseMiddleClick() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_MIDDLE_CLICK.getPath());
	}

	public void doubleClick() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_DOUBLE_CLICK.getPath());
	}

	public void mouseDown() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_DOWN.getPath());
	}

	public void drag() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_DRAG.getPath());
	}

	public void mouseRelease() {
		Map valueNode = new HashMap<>();
		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_RELEASE.getPath());
	}

	public void mouseWheel(int delta) {
		Map valueNode = new HashMap<>();
		valueNode.put("delta", delta);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.MOUSE_WHEEL.getPath());
	}


	//---------------------------------------------------------------------------------------------------------------------------
	// get elements
	//---------------------------------------------------------------------------------------------------------------------------

	public List getWebElementsListByHandle(TestBound channelDimension, int handle, long pid) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("pid", pid);

		List list = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_LOAD_TREE.getPath()).getFoundElements(channelDimension);


		List flatList = new ArrayList<>();
		for (FoundElement item : list) {
			item.flatten(flatList);
		}
		
		flatList.sort(Comparator.comparingDouble(FoundElement::getArea));
		return flatList;
	}

	public void defineRoot(TestBound channelDimension, String id) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", id);

		setElementMapLocation(sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_ROOT.getPath()).getFoundElements(channelDimension));
	}

	public void refreshElementMapLocation(Channel channel) {
		new Thread(new LoadMapElement(channel, this)).start();
	}

	public void refreshElementMap(Channel channel) {
		setElementMapLocation(getWebElementsListByHandle(channel.getDimension(), channel.getHandle(this), channel.getProcessId()));
	}

	public void setElementMapLocation(List list) {
		final FoundElement parent = new FoundElement();
		list.forEach(e -> recalculateSize(parent, e));
		this.elementMapLocation = list;
	}

	private void recalculateSize(FoundElement parent, FoundElement elem) {
		if (elem.getScreenX() == 1 &&  elem.getScreenY() == 1 && elem.getWidth() == 1 && elem.getHeight() == 1) {
			//specific case of a formless element in a tree object
			elem.updateSize(parent.getScreenX(), parent.getScreenY(), parent.getWidth(), parent.getHeight(), parent.getX(), parent.getY());
		}

		if(elem.isVisible() && elem.getWidth() > 0 && elem.getHeight() > 0) {
			parent.updateSize(elem.getBoundX() + elem.getWidth(), elem.getBoundY() + elem.getHeight());
		}

		if(elem.getChildren() != null) {
			elem.getChildren().parallelStream().forEach(e -> recalculateSize(elem, e));
		}
	}

	public FoundElement getElementFromPoint(final Double x, final Double y) {

		final double xPos = x;
		final double yPos = y - 10;

		if (elementMapLocation != null && !elementMapLocation.isEmpty()) {
			final Optional fe = elementMapLocation.stream().filter(e -> e.isActive() && e.getRectangle().contains(xPos, yPos)).findFirst();
			if(fe.isPresent()) {
				return getHoverChild(fe.get(), xPos, yPos);
			}
		}
		return null;
	}

	private FoundElement getHoverChild(final FoundElement elem, final double xPos, final double yPos) {
		if(elem.getChildren() != null && !elem.getChildren().isEmpty()) {
			final Optional child = elem.getChildren().stream().parallel().filter(e -> e.isActive() && e.getRectangle().contains(xPos, yPos)).parallel().sorted((a,b)->-1).findFirst();//.sorted(compareElementBySize)
			if(child.isPresent()) {
				return getHoverChild(child.get(), xPos, yPos);
			}
		}
		return elem;
	}

	public FoundElement getElementFromRect(Double x, Double y, Double w, Double h) {
		FoundElement hoverElement = null;
		if (elementMapLocation != null) {
			for (FoundElement testElement : elementMapLocation) {
				if(testElement != null && testElement.isVisible()){
					if (hoverElement == null) {
						hoverElement = testElement;
						continue;
					}

					final Rectangle rect = testElement.getRectangle();

					if (!rect.contains(x, y)
							|| rect.getWidth() > w || rect.getHeight() > h
							|| hoverElement.getWidth() <= testElement.getWidth()
							&& hoverElement.getHeight() <= testElement.getHeight()) continue;
					hoverElement = testElement;
				}
			}
		}
		return hoverElement;
	}

	public FoundElement getRootElement(Channel channel) {
		return getRootElement(channel.getHandle(this));
	}

	public FoundElement getRootElement(int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);

		return new FoundElement(sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_HANDLE.getPath()).getWindow());
	}

	public List getContextMenu(Channel channel) {
		Map valueNode = new HashMap<>();
		valueNode.put("pid", channel.getProcessId());

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_CONTEXT_MENU.getPath()).getFoundElements(channel.getDimension());
	}

	//---------------------------------------------------------------------------------------------------------------------------
	// manage
	//---------------------------------------------------------------------------------------------------------------------------

	public List getShapes(TestBound channelDimension, String duration, String device, int[] rect) throws Exception{
		Map valueNode = new HashMap<>();
		valueNode.put("duration", duration);
		valueNode.put("device", device);
		valueNode.put("crop", Arrays.stream(rect).mapToObj(String::valueOf).collect(Collectors.joining(",")));

		final DesktopResponse resp = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.DRIVER_SHAPES.getPath());

		if(resp.getErrorCode() != 0) {
			throw new Exception(resp.getErrorMessage());
		}else {
			return resp.getData();
		}
	}

	public DesktopResponse startApplication(boolean attach, ArrayList args) {
		Map valueNode = new HashMap<>();
		valueNode.put("attach", attach);
		valueNode.put("args", String.join("\n", args));

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.DRIVER_APPLICATION.getPath());
	}

	public List getWindowsByPid(long pid) {
		Map valueNode = new HashMap<>();
		valueNode.put("pid", pid);

		DesktopResponse response = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_LIST.getPath());

		return response.getWindows();
	}

	public void updateWindowHandle(Channel channel) {
		int handle = channel.getHandle(this);
		if(handle > 0) {
			Map valueNode = new HashMap<>();
			valueNode.put("handle", handle);

			getEngine().setWindow(sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_HANDLE.getPath()).getWindow());

		}
	}

	public void closeDialogBoxes(long pid) {
		Map valueNode = new HashMap<>();
		valueNode.put("pid", pid);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_CLOSE_MODAL_WINDOWS.getPath());
	}

	public DesktopWindow getWindowByHandle(int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_HANDLE.getPath()).getWindow();
	}

	public DesktopWindow getWindowByTitle(String title, String name) {
		return DesktopWindow.createWindow(getWindowByTiltleOrName(title, name));
	}

	public DesktopWindow openExplorerWindow() {
		return DesktopWindow.createWindow(sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_EXPLORER.getPath()));
	}

	public void setChannelToFront(int handle, long pid) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("pid", pid);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_TO_FRONT.getPath());
	}

	public void setWindowToFront(long pid, int handle) {
		setChannelToFront(handle, pid);
	}

	public void rootKeys(int handle, String keys) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("keys", keys);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_KEYS.getPath());
	}

	public void moveWindow(Channel channel, Point point) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", channel.getHandle(this));
		valueNode.put("value1", point.x);
		valueNode.put("value2", point.y);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_MOVE.getPath());
	}

	public void resizeWindow(Channel channel, Dimension size) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", channel.getHandle(this));
		valueNode.put("value1", size.width);
		valueNode.put("value2", size.height);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_RESIZE.getPath());
	}

	public void switchTo(Channel channel, int index) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", channel.getHandle(this, index));

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_SWITCH.getPath());
	}

	public DesktopResponse switchTo(long processId, int index, int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("index", index);
		valueNode.put("pid", processId);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_SWITCH.getPath());
	}

	public void closeWindow(Channel channel) {
		closeWindow(channel.getHandle(this));
	}

	public void closeWindow(int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_CLOSE.getPath());
	}

	public void closeExplorerWindow(int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_CLOSE_WINDOW.getPath());
	}

	public void windowState(ActionStatus status, Channel channel, String state) {
		windowState(status, channel.getHandle(this), state);
	}

	public void windowState(ActionStatus status, int handle, String state) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("state", state);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.WINDOW_STATE.getPath());
	}

	public void ostracon(ActionStatus status, int handle) {
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.DRIVER_OSTRACON.getPath());
	}

	public void gotoUrl(ActionStatus status, int handle, String url) {
		status.setData(url);
		Map valueNode = new HashMap<>();
		valueNode.put("handle", handle);
		valueNode.put("url", url);

		final DesktopResponse resp = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.WINDOW_URL.getPath());

		if(resp.getErrorCode() < 0) {
			status.setError(resp.getErrorCode(), resp.getErrorMessage());
		}else {
			status.setPassed(true);
		}
	}

	public FoundElement getTestElementParent(String elementId, Channel channel){
		Map valueNode = new HashMap<>();
		valueNode.put("id", elementId);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_PARENTS.getPath()).getParentsElement(channel.getDimension());
	}

	public CalculatedProperty[] getElementAttributes(String elementId) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", elementId);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_ATTRIBUTES.getPath()).getElementAttributes();
	}

	public String getTextData(String id) {//TODO implement text data
		return "";
	}

	public List executeScript(ActionStatus status, String script, FoundElement element) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", element.getId());
		valueNode.put("script", script);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_SCRIPT.getPath()).getData();
	}

	public void elementFocus(FoundElement element) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", element.getId());

		sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_FOCUS.getPath());
	}

	public List findElements(Channel channel, TestElement testElement, String tag, String[] attributes, Predicate predicate) {
		Map valueNode = new HashMap<>();
		valueNode.put("tag", tag);
		valueNode.put("attributes", attributes);
		DesktopResponse resp ;

		if(testElement.getParent() != null){
			valueNode.put("id", testElement.getParent().getWebElementId());
			resp = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_CHILDS.getPath());
		}else{
			valueNode.put("handle", channel.getHandle(this));
			resp = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_FIND.getPath());
		}
		
		return resp.getFoundElements(predicate, channel.getDimension());
	}

	public List getListItems(TestBound dimension, String comboId){
		Map valueNode = new HashMap<>();
		valueNode.put("id", comboId );

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_LIST_ITEMS.getPath()).getFoundElements(dimension);
	}

	public List getChildren(TestBound dimension, String comboId, String tag){
		Map valueNode = new HashMap<>();
		valueNode.put("id", comboId );
		valueNode.put("tag", tag);

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_CHILDS.getPath()).getFoundElements(dimension);
	}

	public void selectItem(ActionStatus status, String elementId, String type, String value, boolean regexp) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", elementId );
		valueNode.put("type", type);
		valueNode.put("value", value);
		valueNode.put("regexp", regexp);

		final DesktopResponse resp = sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_SELECT.getPath());

		if(resp.getErrorMessage() != null) {
			status.setError(ActionStatus.OBJECT_NOT_FOUND, resp.getErrorMessage());
		}
	}

	public String getElementAttribute(String elementId, String attribute) {
		Map valueNode = new HashMap<>();
		valueNode.put("id", elementId );
		valueNode.put("attribute", attribute );

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_ATTRIBUTES.getPath()).getFirstAttribute();
	}

	public List getDialogBox(TestBound dimension, Long pId) {
		Map valueNode = new HashMap<>();
		valueNode.put("pId", pId );

		return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.ELEMENT_DIALOG_BOX.getPath()).getFoundElements(dimension);
	}

	private static class LoadMapElement	implements Runnable {
		final TestBound channelDimension;
		final int handle;
		final long pid;
		final SystemDriver driver;

		public LoadMapElement(Channel channel, SystemDriver driver) {
			this.channelDimension = channel.getDimension();
			this.handle = channel.getHandle(driver);
			this.pid = channel.getProcessId();
			this.driver = driver;
		}

		@Override
		public void run() {
			driver.setElementMapLocation(driver.getWebElementsListByHandle(channelDimension, handle, pid));
		}
	}

	//---------------------------------------------------------------------------------------
	//visual actions
	//---------------------------------------------------------------------------------------
	private IDriverInfo getDriverInfo() {
		if(AtsSingleton.getInstance().getCurrentChannel() != null && AtsSingleton.getInstance().getCurrentChannel().getDriverEngine() != null) {
			return AtsSingleton.getInstance().getCurrentChannel().getDriverEngine().getDriverInfo();
		}
		return null;
	}

	public void saveSummary(ScriptStatus status, TestSummary summary) {

		final RecorderSummaryData recorder = summary.getRecordSummary(status, getDriverInfo());
		sendRequestCommand(HttpMethod.POST, JsonUtils.createPostData(recorder), ApiRoute.RECORDER_SUMMARY.getPath());
	}

	public void stopVisualRecord() {
		Map valueNode = new HashMap<>();
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson());

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_STOP.getPath());
	}

	public byte[] getScreenshotByte(Double x, Double y, Double w, Double h){

		byte[] img = null;

		final String url = systemDriverInfo.getDriverHostAndPort()
				.append("/screencapture/")
				.append(x.intValue()).append(",")
				.append(y.intValue()).append(",")
				.append(w.intValue()).append(",")
				.append(h.intValue())
				.toString();

		final Request request = new Request.Builder()
				.url(url)
				.addHeader("User-Agent", USER_AGENT_NAME)
				.get()
				.build();

		Response response = null;
		try {
			response = client.newCall(request).execute();

			if(response.body() != null){
				img = response.body().bytes();
			}

			response.close();
		} catch (IOException e) {

		}finally {
			try {
				if(response != null) {
					if(response.body() != null) {
						response.body().close();
					}
					response.close();
				}
			}catch(Exception e) {}
		}

		return img;
	}

	public byte[] getMobileScreenshotByte(String url){

		byte[] img = null;

		final Request request = new Request.Builder()
				.url(url)
				.addHeader("User-Agent", USER_AGENT_NAME)
				.addHeader("Content-Type", "text/plain")
				.post(RequestBody.Companion.create("hires", Utils.TEXT_MEDIA))
				.build();

		Response response = null;
		try {
			response = client.newCall(request).execute();
			if(response.body() != null){
				img = response.body().bytes();
			}
			response.close();
		} catch (IOException e) {

		}finally {
			try {
				if(response != null) {
					if(response.body() != null) {
						response.body().close();
					}
					response.close();
				}
			}catch(Exception e) {}
		}

		return img;
	}

	public void createMobileRecord(boolean stop, String actionType, int scriptLine, String scriptName, long timeline, String channelName, TestBound subDimension, String screenshotPath, boolean sync){
		Map valueNode = new HashMap<>();
		valueNode.put("actionType", actionType );
		valueNode.put("line", scriptLine );
		valueNode.put("script", scriptName );
		valueNode.put("timeLine", timeline );
		valueNode.put("channelName", channelName);
		valueNode.put("channelDimensionX", subDimension.getX().intValue());
		valueNode.put("channelDimensionY", subDimension.getY().intValue());
		valueNode.put("channelDimensionWidth", subDimension.getWidth().intValue());
		valueNode.put("channelDimensionHeight", subDimension.getHeight().intValue());
		valueNode.put("url", screenshotPath);
		valueNode.put("sync", sync);
		valueNode.put("stop", stop);
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_CREATE_MOBILE.getPath());
	}

	public void createVisualAction(Channel channel, boolean stop, String actionType, int scriptLine, String scriptName, long timeline, boolean sync) {
		Map valueNode = new HashMap<>();
		valueNode.put("actionType", actionType );
		valueNode.put("line", scriptLine );
		valueNode.put("script", scriptName );
		valueNode.put("timeLine", timeline );
		valueNode.put("channelName", channel.getName());
		valueNode.put("channelDimensionX", channel.getDimension().getX().intValue());
		valueNode.put("channelDimensionY", channel.getDimension().getY().intValue());
		valueNode.put("channelDimensionWidth", channel.getDimension().getWidth().intValue());
		valueNode.put("channelDimensionHeight", channel.getDimension().getHeight().intValue());
		valueNode.put("sync", sync);
		valueNode.put("stop", stop);
		if(getDriverInfo() != null)	{
			valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));
		}

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_CREATE.getPath());
	}

	public void updateMobileScreenshot(TestBound bound, boolean isRef,String url){
		Map valueNode = new HashMap<>();
		double[] screenRect = {0,0,bound.getWidth().intValue(),bound.getHeight().intValue()};
		valueNode.put("screenRect", screenRect );
		valueNode.put("isRef", isRef );
		valueNode.put("url", url );
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_IMAGE_MOBILE.getPath());
	}

	public DesktopResponse startVisualRecord(ScriptHeader header, int quality, long started) {
		Map valueNode = header.getJsonData(quality,started);
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));

		if(AtsSingleton.getInstance().getCurrentChannel() != null && AtsSingleton.getInstance().getCurrentChannel().getDriverEngine() != null) {
			return sendDesktopRequest(valueNode,HttpMethod.POST, ApiRoute.RECORDER_START.getPath());
		}
		return null;
	}

	public void startVisualRecord(Channel channel, ScriptHeader header, int quality, long started) {
		Map valueNode = header.getJsonData(quality,started);
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_START.getPath());
	}

	public void updateVisualImage(TestBound dimension, boolean isRef) {
		Map valueNode = new HashMap<>();
		double[] screenRect = {dimension.getX().intValue(),dimension.getY().intValue(),dimension.getWidth().intValue(),dimension.getHeight().intValue()};
		valueNode.put("screenRect", screenRect );
		valueNode.put("isRef", isRef );
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_IMAGE.getPath());
	}

	public void updateVisualValue(String value) {
		Map valueNode = new HashMap<>();
		valueNode.put("v", value );

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_VALUE.getPath());
	}

	public void updateVisualData(String value, String data) {
		Map valueNode = new HashMap<>();
		valueNode.put("v1", value );
		valueNode.put("v2", data );

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_DATA.getPath());
	}

	public void updateVisualStatus(int error, long duration) {
		Map valueNode = new HashMap<>();
		valueNode.put("error", error );
		valueNode.put("duration", duration );

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_STATUS.getPath());
	}

	public void updateVisualElement(TestElement element) {
		if(isEnabled() ) {
			Map valueNode = new HashMap<>();
			Double[] elementBound = element.getBound();

			TestElement e = element;
			String selector = e.getSelector();
			while(selector.isEmpty() && e.getParent() != null) {
				e = e.getParent();
				selector = e.getSelector();
			}

			if(selector.length() > 100) {
				selector = selector.substring(0, 100);
			}

			Arrays.setAll(elementBound, j -> elementBound[j] == null ? 0D : elementBound[j].intValue());
			valueNode.put("searchDuration", element.getTotalSearchDuration() );
			valueNode.put("elementBound", elementBound );
			valueNode.put("numElements", element.getElementsCount() );
			valueNode.put("selector", selector );
			valueNode.put("tag", element.getSearchedTag() );

			sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_ELEMENT.getPath());
		}
	}

	public void updateVisualPosition(String type, MouseDirectionData hdir, MouseDirectionData vdir) {
		Map valueNode = new HashMap<>();

		updateVisualValue(type);

		String hdirName = "";
		int hdirValue = 0;

		String vdirName = "";
		int vdirValue = 0;

		if(hdir != null) {
			hdirName = hdir.getName();
			hdirValue = hdir.getIntValue();
		}

		if(vdir != null) {
			vdirName = vdir.getName();
			vdirValue = vdir.getIntValue();
		}
		valueNode.put("hpos", hdirName );
		valueNode.put("hposValue", hdirValue );
		valueNode.put("vpos", vdirName );
		valueNode.put("vposValue", vdirValue );

		sendRequestCommandVoid(valueNode,HttpMethod.POST, ApiRoute.RECORDER_POSITION.getPath());
	}

	//---------------------------------------------------------------------------------------
	//---------------------------------------------------------------------------------------

	private final static String USER_AGENT_NAME = "AtsDesktopDriver";

	public JsonNode getWindowHandle(String sessionId){
		return sendRequestCommand(HttpMethod.GET, ApiRoute.ATS_SESSION.getPath());
	}
	
	public void saveVisualReportFile(Path path, ExecutionLogger logger) {

		Map valueNode = new HashMap<>();
		if(getDriverInfo() != null)	valueNode.put("driverInfo", Objects.requireNonNull(getDriverInfo()).toJson().get("driverInfo"));
		ObjectMapper mapper = new ObjectMapper();
		ObjectNode node = JsonUtils.createPostData(mapper, valueNode);

		final StringBuilder urlBuilder = systemDriverInfo.getDriverHostAndPort();
		for (String data : ApiRoute.RECORDER_DOWNLOAD.getPath()) {
			urlBuilder.append("/").append(data);
		}
		final okhttp3.Request.Builder request = new Request.Builder().url(urlBuilder.toString()).addHeader("User-Agent", USER_AGENT_NAME);
		request.post(RequestBody.Companion.create(node.toString(), Utils.JSON_MEDIA));

		setDownloadTimeout();

		Response response = null;
		try {
			response = client.newCall(request.build()).execute();

			if(response.code() == 200 && response.body() != null) {

				final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path.toFile()));
				final BufferedInputStream bis = new BufferedInputStream(response.body().byteStream());

				int totalByte = 0;
				int inByte;
				while((inByte = bis.read()) != -1) {
					bos.write(inByte);
					totalByte += inByte;
				}

				bis.close();
				bos.close();

				totalByte = (int) (totalByte * 0.000008);

				logger.sendInfo("save ATSV file", path.toString() + " (" + totalByte + " Ko)");

			}else {
				logger.sendError("unable to save ATSV file", response.message());
			}

			response.close();

		} catch (IOException e) {
			logger.sendError("error saving ATSV file", e.getMessage());
		}finally {
			try {
				if(response != null) {
					if(response.body() != null) {
						response.body().close();
					}
					response.close();
				}
			}catch(Exception e) {}
		}

		setNormalTimeout();
	}

	public String getSource() {
		return new Gson().toJson(elementMapLocation);
	}

	//--------------------------------------------------------------------------------------------------------------------------------
	// New send command W3C compliant
	//--------------------------------------------------------------------------------------------------------------------------------

	public JsonNode getUserFolder(String profile, String browserName){
		ObjectMapper mapper = new ObjectMapper();
		Map valueNode = new HashMap<>();
		valueNode.put("userProfile", profile);
		valueNode.put("browserName", browserName);

		return sendRequestCommand(HttpMethod.POST, JsonUtils.createPostData(mapper, valueNode),ApiRoute.ATS_PROFILE.getPath());
	}

	public JsonNode getWindowByTiltleOrName(String title, String name){
		ObjectMapper mapper = new ObjectMapper();
		Map valueNode = new HashMap<>();
		valueNode.put("title", title);
		valueNode.put("name", name);

		return sendRequestCommand(HttpMethod.POST, JsonUtils.createPostData(mapper, valueNode),ApiRoute.ATS_WINDOW.getPath());
	}

	private JsonNode sendRequestCommand(HttpMethod method, String ... urlData) {
		return sendRequestCommand(method, null, urlData);
	}

	/*!
	 * @brief sendDesktopRequest
	 * @detail Send request to the driver in json format
	 * @param valueNode Map sting, object (key : value)
	 * @param method Http method
	 * @param urlData Url data
	 * @return DesktopResponse
	 */
	private DesktopResponse sendDesktopRequest(Map valueNode, HttpMethod method, String... urlData) {
		ObjectMapper mapper = new ObjectMapper();
		ObjectNode postData = JsonUtils.createPostData(mapper, valueNode);
		JsonNode result = sendRequestCommand(method, postData, urlData);
		return new DesktopResponse(result);
	}

	/*!
	 * @brief sendRequestCommandVoid
	 * @detail Send request to the driver in json format
	 * @param method Http method
	 * @param valueNode Map sting, object (key : value)
	 * @param urlData Url data
	 */
	private void sendRequestCommandVoid(Map valueNode, HttpMethod method, String... urlData) {
		ObjectMapper mapper = new ObjectMapper();
		ObjectNode postData = JsonUtils.createPostData(mapper, valueNode);
		sendRequestCommand(method, postData, urlData);
	}

	/*!
	 * @brief sendRequestCommand
	 * @detail Send request to the driver in json format
	 * @param method Http method
	 * @param node Json node
	 * @param urlData Url data
	 * @return JsonNode
	 */
	private JsonNode sendRequestCommand(HttpMethod method, ObjectNode node, String ... urlData) {

		JsonNode result;

		final StringBuilder urlBuilder = systemDriverInfo.getDriverHostAndPort();

		for (String data : urlData) {
			urlBuilder.append("/").append(data);
		}

		final okhttp3.Request.Builder request =
				new Request.Builder()
				.url(urlBuilder.toString())
				.addHeader("User-Agent", USER_AGENT_NAME)
				.addHeader(ATS_CLIENT_ID, systemDriverInfo.getUuid());

		if(method == HttpMethod.POST) {
			String jsonContent;
			if(node == null) {
				ObjectNode nullNode = mapper.createObjectNode();
				nullNode.putNull("value");
				jsonContent = nullNode.toString();
			}
			else{
				jsonContent = node.toString();
			}
			request.post(RequestBody.Companion.create(jsonContent, Utils.JSON_MEDIA));
		}else if(method == HttpMethod.GET) {
			request.get();
		}else if(method == HttpMethod.DELETE) {
			request.delete(null);
		}

		Response response = null;
		try {
			response = client.newCall(request.build()).execute();
			if(response.body() != null) {

				final JsonNode responseNode = mapper.readValue(response.body().byteStream(), JsonNode.class);
				response.close();

				if (responseNode.has("value")) {
					JsonNode valueNode = responseNode.get("value");
					if (valueNode.isObject() && valueNode.has("error")) {
						String errorValue = valueNode.get("error").asText();
						if (errorValue.equals(ERROR_ATS_DESKTOP_RESPONSE)) {
							result = valueNode.get("datas");
						} else {
							result = responseNode.get("value");
						}
					} else {
						result = responseNode.get("value");
					}
				} else {
					final ObjectNode o = mapper.createObjectNode();
					final ObjectNode error = o.putObject("error");
					error.put("message", responseNode.toString());

					result = o;
				}
			}
			else{
				final ObjectNode o = mapper.createObjectNode();
				final ObjectNode error = o.putObject("error");
				error.put("message", "No response from driver");
				result = o;
			}
		} catch (IOException e) {
			final ObjectNode o = mapper.createObjectNode();
			final ObjectNode error = o.putObject("error");
			error.put("message", e.getMessage());

			result = o;
		}finally {
			try {
				if(response != null) {
					if(response.body() != null) {
						response.body().close();
					}
					response.close();
				}
			}catch(Exception e) {}
		}
		return result;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy