initialize
This commit is contained in:
21
interface/cogiscan/plugin/src/main/assembly/descriptor.xml
Normal file
21
interface/cogiscan/plugin/src/main/assembly/descriptor.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
|
||||
<id>bin</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<outputDirectory/>
|
||||
<includes>
|
||||
<include>*dependencies*.jar</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>*.zip</exclude>
|
||||
</excludes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
public class CogiscanException extends Exception {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -9180600020616111590L;
|
||||
private ResponseDetail responseDetail;
|
||||
|
||||
public CogiscanException(ResponseDetail responseDetail) {
|
||||
this.responseDetail = responseDetail;
|
||||
}
|
||||
|
||||
public ResponseDetail getResponseDetail() {
|
||||
return responseDetail;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
public interface CogiscanFields {
|
||||
|
||||
public static final String PLACEMENT_COMPONENT_ID = "placement.componentId";
|
||||
public static final String PLACEMENT_LIST = "placementList";
|
||||
public static final String EVENT_DATE = "eventDate";
|
||||
public static final String STATUS = "status";
|
||||
public static final String MESSAGE_DETAIL = "messageDetail";
|
||||
public static final String MESSAGE_STOP = "messageStop";
|
||||
public static final String MESSAGE_START = "messageStart";
|
||||
public static final String MESSAGE_CODE = "messageCode";
|
||||
public static final String MACHINE_PLACEMENTS = "machinePlacements";
|
||||
public static final String END_PRODUCTION = "endProduction";
|
||||
public static final String START_PRODUCTION = "startProduction";
|
||||
public static final String STATE = "state";
|
||||
public static final String PLACEMENT_RECIPE_NAME = "placementRecipeName";
|
||||
public static final String SERIAL_NUMBER = "serialNumber";
|
||||
public static final String CONTAINER_COMPONENT_ID = "container.componentId";
|
||||
public static final String CONTAINER_CONTAINER_ID = "container.containerId";
|
||||
public static final String OPERATION = "operation";
|
||||
public static final String MACHINE_PLACEMENT_HANDLER_INFO = "machinePlacement.handlerInfo";
|
||||
public static final String PLACEMENT_PANEL_NUMBER = "placement.panelNumber";
|
||||
public static final String PLACEMENT_DESIGNATOR = "placement.designator";
|
||||
public static final String PLACEMENTS = "placements";
|
||||
public static final String HANDLER_ID = "handlerId";
|
||||
public static final String CONTAINER_ID = "containerId";
|
||||
public static final String COMPONENT_ID = "componentId";
|
||||
public static final String CONTAINER = "container";
|
||||
public static final String LANE = "lane";
|
||||
public static final String LINE_NAME = "lineName";
|
||||
public static final String MACHINE_NAME = "machineName";
|
||||
public static final String MACHINE = "machine";
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class DateAdapter {
|
||||
|
||||
private static SimpleDateFormat sdf = ((SimpleDateFormat) SimpleDateFormat.getDateTimeInstance());
|
||||
|
||||
static {
|
||||
sdf.applyPattern("yyyy-MM-dd'T'HH:mm:ss.S Z");
|
||||
}
|
||||
|
||||
public static Date parseDate(String s) {
|
||||
try {
|
||||
return sdf.parse(s);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new Date(0);
|
||||
}
|
||||
|
||||
public static String printDate(Date dt) {
|
||||
return sdf.format(dt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.itac.mes.cogiscan.data.FailoverHost;
|
||||
import com.itac.mes.datainterface.data.IMesServicesLog;
|
||||
|
||||
public class FailoverHostList {
|
||||
|
||||
// this list is cyclically updated as long as a mesService Endpoint is active and not closed
|
||||
private List<FailoverHost> failoverHosts;
|
||||
// this is the host all current calls are going to
|
||||
private FailoverHost activeHost;
|
||||
private IMesServicesLog log;
|
||||
|
||||
/**
|
||||
* @param log
|
||||
* if log is null (which is allowed) simply usse the System. out for logging
|
||||
*/
|
||||
public FailoverHostList(IMesServicesLog log) {
|
||||
super();
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public IMesServicesLog getLog() {
|
||||
if (log == null) {
|
||||
log = new IMesServicesLog() {
|
||||
|
||||
@Override
|
||||
public void out(String text) {
|
||||
System.out.println(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void err(String text) {
|
||||
System.err.println(text);
|
||||
}
|
||||
};
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
public void setFailover(List<FailoverHost> newFailoverHosts) {
|
||||
// protokolliren, was sich geändert hat
|
||||
boolean newHosts = false;
|
||||
if (newFailoverHosts == null) {
|
||||
activeHost = null;
|
||||
this.failoverHosts = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.failoverHosts == null) {
|
||||
// initial setting
|
||||
getLog().out("setting initial failover hosts :");
|
||||
for (FailoverHost item : newFailoverHosts) {
|
||||
getLog().out(": " + item.getHostname());
|
||||
}
|
||||
} else {
|
||||
// whats new, whats removed...
|
||||
Map<String, FailoverHost> currentHosts = new HashMap<String, FailoverHost>();
|
||||
for (FailoverHost item : this.failoverHosts) {
|
||||
currentHosts.put(item.getHostname(), item);
|
||||
}
|
||||
|
||||
for (FailoverHost item : newFailoverHosts) {
|
||||
if (currentHosts.containsKey(item.getHostname())) {
|
||||
// enthalten, also aus dieser Liste lösche
|
||||
currentHosts.remove(item.getHostname());
|
||||
} else {
|
||||
// bisher nicht enthalten, also neu
|
||||
getLog().out("new failover host " + item.getHostname());
|
||||
newHosts = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentHosts.size() > 0) {
|
||||
getLog().out("some failover host removed ");
|
||||
for (FailoverHost removedHost : currentHosts.values()) {
|
||||
getLog().out(" - " + removedHost.getHostname());
|
||||
}
|
||||
} else {
|
||||
if (!newHosts) {
|
||||
getLog().out("failover host list remains unchanged ");
|
||||
for (FailoverHost item : newFailoverHosts) {
|
||||
getLog().out(":" + item.getHostname());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.failoverHosts = newFailoverHosts;
|
||||
|
||||
// der erste Host in der Liste ist auch der Host, zu dem die aufrufe ohne Failover gehen!!!
|
||||
if (activeHost == null) {
|
||||
if (newFailoverHosts.size() > 0) {
|
||||
activeHost = newFailoverHosts.get(0);
|
||||
} else {
|
||||
// clean default host
|
||||
activeHost = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a host from the failover list.
|
||||
*
|
||||
* If the host is the currently active host {@link #getActiveHost()} then the current host is set to null<br>
|
||||
* If the host is not in the host list then nothing happens
|
||||
*
|
||||
* @param host
|
||||
* the host to be removed; do nothing if host is null
|
||||
*/
|
||||
public void remove(FailoverHost host) {
|
||||
if (host == null) {
|
||||
return;
|
||||
}
|
||||
getLog().out("remove host " + host.getHostname() + " from failover list");
|
||||
for (int i = 0; i < getList().size(); i++) {
|
||||
FailoverHost item = getList().get(i);
|
||||
if (item.getHostname().equals(host.getHostname())) {
|
||||
getList().remove(i);
|
||||
getLog().out("host " + item.getHostname() + " removed from failover list");
|
||||
}
|
||||
}
|
||||
if (activeHost != null && activeHost.getHostname().equals(host.getHostname())) {
|
||||
setActiveHost(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of hosts in the failover list
|
||||
*/
|
||||
public int size() {
|
||||
return failoverHosts == null ? 0 : failoverHosts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of currently known host to fail over
|
||||
*/
|
||||
public List<FailoverHost> getList() {
|
||||
return failoverHosts == null ? new ArrayList<FailoverHost>() : failoverHosts;
|
||||
}
|
||||
|
||||
public FailoverHost getActiveHost() {
|
||||
return activeHost;
|
||||
}
|
||||
|
||||
public void setActiveHost(FailoverHost host) {
|
||||
if (host == null) {
|
||||
getLog().out("clear active failover hosts");
|
||||
} else {
|
||||
getLog().out("set " + host.getHostname() + " as active failover hosts");
|
||||
}
|
||||
this.activeHost = host;
|
||||
}
|
||||
|
||||
public FailoverHost getNextFailoverHost() {
|
||||
FailoverHost failoverHost = null;
|
||||
getLog().out("scanning for other failover hosts. list contains a total of " + size() + " hosts");
|
||||
for (FailoverHost host : getList()) {
|
||||
if (host.equals(getActiveHost())) {
|
||||
continue;
|
||||
}
|
||||
failoverHost = host;
|
||||
getLog().out("next failover hosts is " + host.getHostname());
|
||||
break;
|
||||
}
|
||||
|
||||
// den nächsten aus der Liste ohne den defaultHost
|
||||
if (size() == 0) {
|
||||
getLog().err("No more failover host available!");
|
||||
}
|
||||
return failoverHost;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.ConnectException;
|
||||
import java.util.List;
|
||||
|
||||
import com.itac.mes.cogiscan.data.ErrorDetail;
|
||||
import com.itac.mes.cogiscan.data.MesFailoverResponse;
|
||||
import com.itac.mes.cogiscan.data.MesResponse;
|
||||
import com.itac.mes.cogiscan.sockets.IhapHandler;
|
||||
import com.itac.mes.datainterface.data.IMesServicesLog;
|
||||
|
||||
public class FailoverInvocationHandler extends FailoverHostList implements InvocationHandler, IFailoverProxy {
|
||||
|
||||
public FailoverInvocationHandler(IMesServicesLog log) {
|
||||
super(log);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a new communication channel with specified name
|
||||
*
|
||||
* @param channelName
|
||||
* the name for the channel
|
||||
* @param connectionListener
|
||||
* @return the communication channel where mesFunctions are exceuted (remote calls via IHap)
|
||||
* @throws IOException
|
||||
*/
|
||||
private synchronized IMesServicesChannel getConnection(String channelName, PropertyChangeListener connectionListener)
|
||||
throws IOException {
|
||||
if (getActiveHost() == null) {
|
||||
getLog().err("cannot get new connection " + channelName + " because active host is unset");
|
||||
return null;
|
||||
}
|
||||
String sHostname = getActiveHost().getHostname();
|
||||
int iPort = getActiveHost().getPort();
|
||||
getLog().out("get new connection " + channelName + " for " + sHostname + ":" + iPort);
|
||||
IMesServicesChannel serviceChannel = IhapHandler.connect(sHostname, iPort, channelName, null, this.getClass().getClassLoader(),
|
||||
getLog());
|
||||
// start the communication channel
|
||||
serviceChannel.startup();
|
||||
return serviceChannel;
|
||||
}
|
||||
|
||||
private void handleThrowable(Object response, Throwable throwable) {
|
||||
if (!(response instanceof MesResponse)) {
|
||||
return;
|
||||
}
|
||||
MesResponse mesResponse = (MesResponse) response;
|
||||
mesResponse.setTotalResult(IMesServices.MES_RESULT_NOT_OK);
|
||||
if (throwable instanceof CogiscanException) {
|
||||
setResponseValues(mesResponse, ((CogiscanException) throwable).getResponseDetail());
|
||||
} else if (throwable instanceof IOException) {
|
||||
mesResponse.getErrorDetails().add(getErrorDetail(throwable.getMessage(), ResponseDetail.COMMUNICATION_FAILURE.getCode()));
|
||||
} else {
|
||||
mesResponse.getErrorDetails().add(getErrorDetail(throwable.getMessage(), ResponseDetail.PROCESSED_WITH_EXCEPTION.getCode()));
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// convenient method
|
||||
private ErrorDetail getErrorDetail(String detail, int code) {
|
||||
ErrorDetail errorDetail = new ErrorDetail();
|
||||
errorDetail.setCode(code);
|
||||
errorDetail.setDetail(detail);
|
||||
return errorDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* finalizing means closing communication channel and loggin response Object
|
||||
*
|
||||
* @param connection
|
||||
* the used connection
|
||||
*/
|
||||
private void finalizeRequest(IMesServicesChannel connection) {
|
||||
if (connection != null) {
|
||||
connection.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized IMesServicesChannel getConnection(String string) throws IOException {
|
||||
return getConnection(string, null);
|
||||
}
|
||||
|
||||
private void setResponseValues(MesResponse response, ResponseDetail responseDetail) {
|
||||
if (responseDetail == ResponseDetail.OK) {
|
||||
response.setTotalResult(IMesServices.MES_RESULT_OK);
|
||||
return;
|
||||
}
|
||||
response.setTotalResult(IMesServices.MES_RESULT_NOT_OK);
|
||||
response.getErrorDetails().add(getErrorDetail(responseDetail.getText(), responseDetail.getCode()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
// special handling for a couple of function (mesStart, mesStop, getFailoverHosts..FailoverInvocationHandler.)
|
||||
Object response = method.getReturnType().newInstance();
|
||||
|
||||
// if no failoverhost available return error
|
||||
if (getActiveHost() == null && size() == 0) {
|
||||
// no host set, no failover available --> fail
|
||||
return null;
|
||||
}
|
||||
|
||||
// do a failover for all methods startswith "mes" (operational methods)
|
||||
if (method.getName().startsWith("mes")) {
|
||||
|
||||
IMesServicesChannel connection = null;
|
||||
|
||||
try {
|
||||
|
||||
boolean callFailed = false;
|
||||
do {
|
||||
try {
|
||||
callFailed = false;
|
||||
getLog().out("call " + method.getName() + "@" + getActiveHost().getHostname());
|
||||
connection = getConnection(method.getName());
|
||||
if (connection == null) {
|
||||
callFailed = true;
|
||||
} else {
|
||||
response = method.invoke(connection, args);
|
||||
if (response == null) {
|
||||
callFailed = true;
|
||||
} else {
|
||||
|
||||
if ((response instanceof MesResponse)) {
|
||||
MesResponse responseObject = (MesResponse) response;
|
||||
if (responseObject.getTotalResult() == MesServices.MES_RESULT_NOT_OK) {
|
||||
// set DetailResult to COMMUNICATION_FAILURE
|
||||
// repeat this call to another host
|
||||
callFailed = hasCommunicationFailure(responseObject.getErrorDetails());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ConnectException ce) {
|
||||
callFailed = true;
|
||||
}
|
||||
|
||||
if (callFailed) {
|
||||
if (connection != null) {
|
||||
connection.shutdown();
|
||||
// explicit finalize this connection
|
||||
connection = null;
|
||||
}
|
||||
remove(getActiveHost());
|
||||
setActiveHost(getNextFailoverHost());
|
||||
}
|
||||
} while (callFailed && getActiveHost() != null);
|
||||
|
||||
// if failover did not find any available host return communication error
|
||||
if (getActiveHost() == null) {
|
||||
|
||||
if ((response instanceof MesResponse)) {
|
||||
MesResponse responseObject = (MesResponse) response;
|
||||
responseObject.getErrorDetails()
|
||||
.add(getErrorDetail("no failover host active", ResponseDetail.COMMUNICATION_FAILURE.getCode()));
|
||||
responseObject.setTotalResult(IMesServices.MES_RESULT_NOT_OK);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(response, throwable);
|
||||
} finally {
|
||||
|
||||
if (response instanceof MesFailoverResponse) {
|
||||
// internally update the list
|
||||
setFailover(((MesFailoverResponse) response).getFailoverHosts());
|
||||
}
|
||||
|
||||
finalizeRequest(connection);
|
||||
}
|
||||
} else {
|
||||
// simply call the method, no failover for them
|
||||
response = method.invoke(proxy, args);
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
private boolean hasCommunicationFailure(List<ErrorDetail> errorDetails) throws ConnectException {
|
||||
if (errorDetails == null) {
|
||||
return false;
|
||||
}
|
||||
for (ErrorDetail errDetail : errorDetails) {
|
||||
if (errDetail.getCode() == ResponseDetail.COMMUNICATION_FAILURE.getCode()) {
|
||||
getLog().err("communication failure on this connection");
|
||||
throw new ConnectException();
|
||||
}
|
||||
if (errDetail.getCode() == -10005) {
|
||||
getLog().err("communication failure on this connection");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.itac.mes.cogiscan.data.FailoverHost;
|
||||
|
||||
public interface IFailoverProxy {
|
||||
|
||||
public void setFailover(List<FailoverHost> failoverHosts);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
public interface IMesServicesChannel extends IMesServices {
|
||||
|
||||
public boolean isShutdown();
|
||||
|
||||
public void startup();
|
||||
|
||||
public void shutdown();
|
||||
|
||||
public String getChannelName();
|
||||
|
||||
public void setChannelName(String channelName);
|
||||
}
|
||||
@@ -0,0 +1,642 @@
|
||||
/*
|
||||
* Copyright (c) 2010 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import static com.itac.mes.cogiscan.ResponseDetail.OK;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.jws.WebService;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import com.itac.mes.cogiscan.data.CheckContainerRequest;
|
||||
import com.itac.mes.cogiscan.data.CheckContainerResponse;
|
||||
import com.itac.mes.cogiscan.data.CreateContainerRequest;
|
||||
import com.itac.mes.cogiscan.data.CreateContainerResponse;
|
||||
import com.itac.mes.cogiscan.data.ErrorDetail;
|
||||
import com.itac.mes.cogiscan.data.FailoverHost;
|
||||
import com.itac.mes.cogiscan.data.InterlockingRequest;
|
||||
import com.itac.mes.cogiscan.data.InterlockingResponse;
|
||||
import com.itac.mes.cogiscan.data.ItemProducedRequest;
|
||||
import com.itac.mes.cogiscan.data.MachineMessageRequest;
|
||||
import com.itac.mes.cogiscan.data.MachineStatusRequest;
|
||||
import com.itac.mes.cogiscan.data.MaterialConsumedRequest;
|
||||
import com.itac.mes.cogiscan.data.MesConfigurationResponse;
|
||||
import com.itac.mes.cogiscan.data.MesFailoverResponse;
|
||||
import com.itac.mes.cogiscan.data.MesRequest;
|
||||
import com.itac.mes.cogiscan.data.MesResponse;
|
||||
import com.itac.mes.cogiscan.data.MesStartRequest;
|
||||
import com.itac.mes.cogiscan.data.PanelInfoRequest;
|
||||
import com.itac.mes.cogiscan.data.PanelInfoResponse;
|
||||
import com.itac.mes.cogiscan.data.PlacementRecipeCheckRequest;
|
||||
import com.itac.mes.cogiscan.data.PlacementRecipeCheckResponse;
|
||||
import com.itac.mes.cogiscan.sockets.IhapHandler;
|
||||
import com.itac.mes.datainterface.data.IMesServicesLog;
|
||||
|
||||
/**
|
||||
* @author frankp created 2011
|
||||
*/
|
||||
@WebService(endpointInterface = "com.itac.mes.cogiscan.IMesServices")
|
||||
public class MesServices implements IMesServices, IMesServicesLog {
|
||||
|
||||
private static String LOG_PREFIX = "iTAC.MES.Suite SMT-Plugin > ";
|
||||
|
||||
/** the port number must be in this allowed range */
|
||||
private static final int MIN_PORT = 1023;
|
||||
private static final int MAX_PORT = 49150;
|
||||
// 10 minutes default
|
||||
private static final long DEFAULT_REFRESH_INTERVAL = 600000;
|
||||
|
||||
// some bool flags for operation
|
||||
private boolean configured;
|
||||
private boolean active;
|
||||
|
||||
private boolean logDetails = true;
|
||||
|
||||
// Ciogiscan needs an own classloader due to unknown reasons
|
||||
private ClassLoader classloader;
|
||||
// every call to a mes host needs an own id; the id does not change when a call is completed on a failover host
|
||||
private RequestIdGenerator idGenerator = new RequestIdGenerator();
|
||||
// the invocation handler accepts all calls from the failoverProxy
|
||||
// additionally this is the way to set properties / values which are not part of the mes... Interface
|
||||
private FailoverInvocationHandler failoverInvocationHandler;
|
||||
// this proxy delegates the calls to all known failover hosts
|
||||
private IMesServices failoverProxy;
|
||||
// context and marshaller for logging
|
||||
private JAXBContext jaxbContext;
|
||||
private Marshaller marshaller;
|
||||
|
||||
// failover detection
|
||||
private static int updateThreadCount;
|
||||
private Thread failoverUpdateThread;
|
||||
|
||||
private long refreshFailoverhostsInterval;
|
||||
|
||||
/**
|
||||
* The default constructor
|
||||
*/
|
||||
private MesServices() {
|
||||
super();
|
||||
setConfigured(false);
|
||||
setActive(false);
|
||||
|
||||
if (System.getProperties().containsKey(MES_LOG_PREFIX)) {
|
||||
LOG_PREFIX = System.getProperty(MES_LOG_PREFIX);
|
||||
}
|
||||
if (System.getProperties().containsKey(MES_LOG_DETAILS)) {
|
||||
String sLogDetails = System.getProperty(MES_LOG_DETAILS);
|
||||
logDetails = sLogDetails.equalsIgnoreCase(Boolean.TRUE.toString()) || sLogDetails.equals("1");
|
||||
}
|
||||
|
||||
// create and initialize the failover proxy
|
||||
failoverInvocationHandler = new FailoverInvocationHandler(this);
|
||||
failoverProxy = (IMesServices) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class<?>[] { IMesServices.class },
|
||||
failoverInvocationHandler);
|
||||
}
|
||||
|
||||
public MesServices(String hostname, int port) {
|
||||
this();
|
||||
if (!isHostNameValid(hostname)) {
|
||||
err("hostname must not be null or empty");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isPortValid(port)) {
|
||||
err(MessageFormat.format("value {0} is out of range {1}..{2}", port, MIN_PORT, MAX_PORT));
|
||||
return;
|
||||
}
|
||||
|
||||
setConfigured(true);
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setHostname(hostname);
|
||||
failoverHost.setPort(port);
|
||||
|
||||
List<FailoverHost> failoverHosts = new ArrayList<FailoverHost>();
|
||||
failoverHosts.add(failoverHost);
|
||||
failoverInvocationHandler.setFailover(failoverHosts);
|
||||
}
|
||||
|
||||
protected void setRefreshFailoverhostsInterval(long refreshFailoverhostsInterval) {
|
||||
this.refreshFailoverhostsInterval = refreshFailoverhostsInterval;
|
||||
}
|
||||
|
||||
protected boolean isPortValid(int newPort) {
|
||||
boolean result = newPort >= MIN_PORT && newPort <= MAX_PORT;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isHostNameValid(String hostname) {
|
||||
return hostname != null && !hostname.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vorbedingungen sind dass der Request gesetzt ist, sowie die Konfiguration und die aktivierung des Plugin
|
||||
*
|
||||
* @param mesResponse
|
||||
* @param mesRequest
|
||||
* @throws CogiscanException
|
||||
*/
|
||||
protected void checkPreconditions(MesResponse mesResponse, MesRequest mesRequest) throws CogiscanException {
|
||||
if (mesRequest == null) {
|
||||
throw new CogiscanException(ResponseDetail.REQUEST_IS_NULL);
|
||||
}
|
||||
if (mesResponse == null) {
|
||||
throw new CogiscanException(ResponseDetail.RESPONSE_IS_NULL);
|
||||
}
|
||||
if (mesRequest.getRequestId() <= 0) {
|
||||
mesRequest.setRequestId(idGenerator.getNextId());
|
||||
}
|
||||
if (mesRequest.getEventDate() == null) {
|
||||
mesRequest.setEventDate(new Date());
|
||||
}
|
||||
// Request ausgeben
|
||||
logRequest(mesRequest);
|
||||
// requestId aus Request in den Response uebernehmen
|
||||
mesResponse.setRequestId(mesRequest.getRequestId());
|
||||
// Konfigurationsprobleme checken
|
||||
if (!isConfigured()) {
|
||||
throw new CogiscanException(ResponseDetail.PLUGIN_NOT_CONFIGURED);
|
||||
}
|
||||
if (!isActive()) {
|
||||
throw new CogiscanException(ResponseDetail.PLUGIN_NOT_ACTIVE);
|
||||
}
|
||||
setResponseValues(mesResponse, OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* finalizing means closing communication channel and loggin response Object
|
||||
*
|
||||
* @param responseObject
|
||||
* the responseObject
|
||||
*/
|
||||
private void finalizeRequest(MesResponse responseObject) {
|
||||
logResponse(responseObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cogiscan has an own classloader; therefore it is necessary for them to set this classloader<br>
|
||||
*
|
||||
* @param classloader
|
||||
* a default classloader if no classloader was set with {@linkplain IhapHandler#setClassLoader}
|
||||
*/
|
||||
private ClassLoader getClassLoader() {
|
||||
if (classloader == null) {
|
||||
classloader = MesServices.class.getClassLoader();
|
||||
}
|
||||
return classloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cogiscan has an own classloader; therefore it is necessary for them to set this classloader<br>
|
||||
* it is not necessary in itac applications such as simulation
|
||||
*
|
||||
* @param classloader
|
||||
*/
|
||||
public void setClassLoader(ClassLoader classloader) {
|
||||
this.classloader = classloader;
|
||||
}
|
||||
|
||||
// convenient method
|
||||
private ErrorDetail getErrorDetail(String detail, int code) {
|
||||
ErrorDetail errorDetail = new ErrorDetail();
|
||||
errorDetail.setCode(code);
|
||||
errorDetail.setDetail(detail);
|
||||
return errorDetail;
|
||||
}
|
||||
|
||||
protected void handleThrowable(MesResponse response, Throwable throwable) {
|
||||
response.setTotalResult(IMesServices.MES_RESULT_NOT_OK);
|
||||
if (throwable instanceof CogiscanException) {
|
||||
setResponseValues(response, ((CogiscanException) throwable).getResponseDetail());
|
||||
} else if (throwable instanceof IOException) {
|
||||
response.getErrorDetails().add(getErrorDetail(throwable.getMessage(), ResponseDetail.COMMUNICATION_FAILURE.getCode()));
|
||||
} else {
|
||||
response.getErrorDetails().add(getErrorDetail(throwable.getMessage(), ResponseDetail.PROCESSED_WITH_EXCEPTION.getCode()));
|
||||
throwable.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void logResponse(MesResponse mesResponse) {
|
||||
if (mesResponse == null) {
|
||||
out("finish request, response is null");
|
||||
return;
|
||||
}
|
||||
if (!logDetails) {
|
||||
out("finish request " + mesResponse.getRequestId() + " with code " + mesResponse.getTotalResult());
|
||||
} else {
|
||||
try {
|
||||
JAXBElement<?> jexbelement = new JAXBElement(new QName(mesResponse.getClass().getSimpleName()), mesResponse.getClass(),
|
||||
mesResponse);
|
||||
StringWriter stw = new StringWriter();
|
||||
getMarshaller().marshal(jexbelement, stw);
|
||||
out(stw.toString());
|
||||
} catch (JAXBException e) {
|
||||
err("no jaxb context or marshaller created");
|
||||
} catch (Throwable e) {
|
||||
err("Error logging mesResponse details");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Marshaller getMarshaller() throws JAXBException {
|
||||
if (marshaller == null) {
|
||||
marshaller = getJaxbContext().createMarshaller();
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
}
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
private JAXBContext getJaxbContext() throws JAXBException {
|
||||
// all classes from the data package
|
||||
if (jaxbContext == null) {
|
||||
Class<?>[] classes = new Class[] { CreateContainerRequest.class, CreateContainerResponse.class, CheckContainerRequest.class,
|
||||
MesFailoverResponse.class, CheckContainerResponse.class, InterlockingRequest.class, InterlockingResponse.class,
|
||||
ItemProducedRequest.class, MachineMessageRequest.class, MachineStatusRequest.class, MaterialConsumedRequest.class,
|
||||
MesConfigurationResponse.class, MesRequest.class, MesResponse.class, PlacementRecipeCheckRequest.class,
|
||||
PlacementRecipeCheckResponse.class };
|
||||
jaxbContext = JAXBContext.newInstance(classes);
|
||||
}
|
||||
return jaxbContext;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void logRequest(MesRequest mesRequest) {
|
||||
if (mesRequest == null) {
|
||||
out("request is null");
|
||||
return;
|
||||
}
|
||||
if (!logDetails) {
|
||||
out("start request " + mesRequest.getRequestId() + " (" + mesRequest.getClass().getSimpleName() + ")");
|
||||
} else {
|
||||
try {
|
||||
JAXBElement<?> jexbelement = new JAXBElement(new QName(mesRequest.getClass().getSimpleName()), mesRequest.getClass(),
|
||||
mesRequest);
|
||||
StringWriter stw = new StringWriter();
|
||||
getMarshaller().marshal(jexbelement, stw);
|
||||
out(stw.toString());
|
||||
} catch (JAXBException e) {
|
||||
err("no jaxb context or marshaller created");
|
||||
} catch (Throwable e) {
|
||||
err("Error logging mesRequest details");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void setResponseValues(MesResponse response, ResponseDetail responseDetail) {
|
||||
if (responseDetail == ResponseDetail.OK) {
|
||||
response.setTotalResult(IMesServices.MES_RESULT_OK);
|
||||
return;
|
||||
}
|
||||
response.setTotalResult(IMesServices.MES_RESULT_NOT_OK);
|
||||
response.getErrorDetails().add(getErrorDetail(responseDetail.getText(), responseDetail.getCode()));
|
||||
}
|
||||
|
||||
protected IMesServices getFailoverProxy() {
|
||||
return failoverProxy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreateContainerResponse mesCreateContainer(CreateContainerRequest createContainerRequest) {
|
||||
CreateContainerResponse responseObject = new CreateContainerResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, createContainerRequest);
|
||||
responseObject = getFailoverProxy().mesCreateContainer(createContainerRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CheckContainerResponse mesCheckContainer(CheckContainerRequest checkContainerRequest) {
|
||||
CheckContainerResponse responseObject = new CheckContainerResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, checkContainerRequest);
|
||||
responseObject = getFailoverProxy().mesCheckContainer(checkContainerRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementRecipeCheckResponse mesCheckPlacementRecipe(PlacementRecipeCheckRequest placementRecipeCheckRequest) {
|
||||
PlacementRecipeCheckResponse responseObject = new PlacementRecipeCheckResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, placementRecipeCheckRequest);
|
||||
responseObject = getFailoverProxy().mesCheckPlacementRecipe(placementRecipeCheckRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterlockingResponse mesInterlocking(InterlockingRequest interlockingRequest) {
|
||||
InterlockingResponse responseObject = new InterlockingResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, interlockingRequest);
|
||||
responseObject = getFailoverProxy().mesInterlocking(interlockingRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PanelInfoResponse mesPanelInformation(PanelInfoRequest infoRequest) {
|
||||
PanelInfoResponse responseObject = new PanelInfoResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, infoRequest);
|
||||
responseObject = getFailoverProxy().mesPanelInformation(infoRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesItemProduced(ItemProducedRequest itemProducedRequest) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, itemProducedRequest);
|
||||
responseObject = getFailoverProxy().mesItemProduced(itemProducedRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesMachineState(MachineStatusRequest machineStatus) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, machineStatus);
|
||||
responseObject = getFailoverProxy().mesMachineState(machineStatus);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesMachineMessage(MachineMessageRequest machineMessage) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, machineMessage);
|
||||
responseObject = getFailoverProxy().mesMachineMessage(machineMessage);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesMaterialConsumed(MaterialConsumedRequest materialConsumedRequest) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, materialConsumedRequest);
|
||||
responseObject = getFailoverProxy().mesMaterialConsumed(materialConsumedRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesConfigurationResponse mesGetConfiguration(MesRequest mesRequest) {
|
||||
MesConfigurationResponse responseObject = new MesConfigurationResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, mesRequest);
|
||||
responseObject = getFailoverProxy().mesGetConfiguration(mesRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
logResponse(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* convienience method, for compatibility with older version
|
||||
*/
|
||||
public MesResponse mesStart(MesRequest mesRequest) {
|
||||
MesStartRequest mesStart = new MesStartRequest();
|
||||
mesStart.setRequestId(mesRequest.getRequestId());
|
||||
mesStart.setEventDate(mesRequest.getEventDate());
|
||||
mesStart.getStartDetails().add("version=1.0");
|
||||
return mesStart(mesStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesStart(MesStartRequest mesRequest) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
// check properties for logging and create marshaller for logging
|
||||
if (System.getProperties().containsKey(MES_LOG_PREFIX)) {
|
||||
LOG_PREFIX = System.getProperty(MES_LOG_PREFIX);
|
||||
}
|
||||
if (System.getProperties().containsKey(MES_LOG_DETAILS)) {
|
||||
String sLogDetails = System.getProperty(MES_LOG_DETAILS);
|
||||
logDetails = sLogDetails.equalsIgnoreCase(Boolean.TRUE.toString()) || sLogDetails.equals("1");
|
||||
}
|
||||
|
||||
// check mes functionality
|
||||
if (mesRequest == null) {
|
||||
throw new CogiscanException(ResponseDetail.REQUEST_IS_NULL);
|
||||
}
|
||||
|
||||
if (!isConfigured()) {
|
||||
throw new CogiscanException(ResponseDetail.MES_NOT_CONFIGURED_PROPERLY);
|
||||
}
|
||||
|
||||
if (isActive()) {
|
||||
// do not ado activation twice
|
||||
setResponseValues(responseObject, ResponseDetail.OK);
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
responseObject = getFailoverProxy().mesStart(mesRequest);
|
||||
long finished = System.nanoTime();
|
||||
out("roundtrip = " + ((finished - start) / 1000L) + " microseconds");
|
||||
if (responseObject.getTotalResult() == MES_RESULT_OK) {
|
||||
setActive(true);
|
||||
startUpdateThread();
|
||||
}
|
||||
} catch (CogiscanException cse) {
|
||||
handleThrowable(responseObject, cse);
|
||||
} finally {
|
||||
logResponse(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
protected void setActive(boolean active) {
|
||||
if (!this.active && active) {
|
||||
out("setting MesServices active");
|
||||
} else if (this.active && !active) {
|
||||
out("setting MesServices inactive");
|
||||
}
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
protected boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
protected boolean isConfigured() {
|
||||
return configured;
|
||||
}
|
||||
|
||||
protected void setConfigured(boolean configured) {
|
||||
if (!this.configured && configured) {
|
||||
out("setting MesServices configured");
|
||||
} else if (this.configured && !configured) {
|
||||
out("setting MesServices configured");
|
||||
}
|
||||
this.configured = configured;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesGetStatus(MesRequest mesRequest) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, mesRequest);
|
||||
responseObject = getFailoverProxy().mesGetStatus(mesRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesResponse mesStop(MesRequest mesRequest) {
|
||||
MesResponse responseObject = new MesResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, mesRequest);
|
||||
responseObject = getFailoverProxy().mesStop(mesRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
setActive(false);
|
||||
stopUpdateThread();
|
||||
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MesFailoverResponse mesGetFailoverList(MesRequest failoverRequest) {
|
||||
MesFailoverResponse responseObject = new MesFailoverResponse();
|
||||
try {
|
||||
checkPreconditions(responseObject, failoverRequest);
|
||||
responseObject = getFailoverProxy().mesGetFailoverList(failoverRequest);
|
||||
} catch (Throwable throwable) {
|
||||
handleThrowable(responseObject, throwable);
|
||||
} finally {
|
||||
finalizeRequest(responseObject);
|
||||
}
|
||||
return responseObject;
|
||||
}
|
||||
|
||||
protected synchronized Thread getUpdateThread() {
|
||||
String threadName = "failoverUpdateThread#" + (updateThreadCount++);
|
||||
Thread failoverUpdateThread = new Thread(threadName) {
|
||||
private int runCounter;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
out(getName() + "renew failoverHost list thread started, call #" + (++runCounter));
|
||||
while (true) {
|
||||
try {
|
||||
if (refreshFailoverhostsInterval < DEFAULT_REFRESH_INTERVAL) {
|
||||
Thread.sleep(DEFAULT_REFRESH_INTERVAL);
|
||||
} else {
|
||||
Thread.sleep(refreshFailoverhostsInterval);
|
||||
}
|
||||
mesGetFailoverList(new MesRequest());
|
||||
out(getName() + "renew failoverHost list finished");
|
||||
} catch (InterruptedException e) {
|
||||
err(getName() + "interrupted or failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
out(getName() + "closed");
|
||||
}
|
||||
};
|
||||
out(threadName + "created");
|
||||
return failoverUpdateThread;
|
||||
}
|
||||
|
||||
protected void startUpdateThread() {
|
||||
// if connection is established and OK start observation thread
|
||||
if (failoverUpdateThread == null || !failoverUpdateThread.isAlive()) {
|
||||
failoverUpdateThread = getUpdateThread();
|
||||
failoverUpdateThread.start();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* the current active channel was closed (port closed on DataInterface)
|
||||
*
|
||||
* @param channelName
|
||||
*/
|
||||
protected void stopUpdateThread() {
|
||||
out(" was closed by iTAC.MES.Suite DataInterface");
|
||||
// den Ueberwachungsthread stoppen
|
||||
if (failoverUpdateThread != null && failoverUpdateThread.isAlive()) {
|
||||
out(" stop " + failoverUpdateThread.getName() + " now");
|
||||
failoverUpdateThread.interrupt();
|
||||
failoverUpdateThread = null;
|
||||
} else {
|
||||
out(" already stopped");
|
||||
}
|
||||
}
|
||||
|
||||
public void out(String text) {
|
||||
System.out.println(LOG_PREFIX + "[MesServices][" + Thread.currentThread().getName() + "] " + text);
|
||||
}
|
||||
|
||||
public void err(String text) {
|
||||
System.err.println(LOG_PREFIX + "[MesServices][" + Thread.currentThread().getName() + "] " + text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
public class RequestIdGenerator {
|
||||
|
||||
protected static int MIN_REQUEST_ID = 0;
|
||||
protected static int MAX_REQUEST_ID = 1000000;
|
||||
|
||||
private int requestId;
|
||||
|
||||
// creates an almost unique id
|
||||
public synchronized int getNextId() {
|
||||
requestId += 1;
|
||||
if (requestId >= MAX_REQUEST_ID) {
|
||||
requestId = MIN_REQUEST_ID;
|
||||
}
|
||||
return requestId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
public enum ResponseDetail {
|
||||
|
||||
// WARNINGS, HINTS: positive values
|
||||
//
|
||||
OK("", 0),
|
||||
// Plugin-ERRORS: negative values
|
||||
REQUEST_IS_NULL("request is null", -10001), //
|
||||
/** any call to MES before mesConfigure was called properly */
|
||||
PLUGIN_NOT_CONFIGURED("plugin not configured", -10002), //
|
||||
PLUGIN_NOT_ACTIVE("plugin not active", -10003), //
|
||||
PLUGIN_NOT_CONNECTED("plugin not connected " + ResponseDetail.MES_DATA_INTERFACE, -10004), //
|
||||
COMMUNICATION_FAILURE("communication failure", -10005), //
|
||||
WRONG_COMMUNICATION_PROPERTIES("communication properties wrong", -10006), //
|
||||
PLUGIN_VERSION_MISMATCH("plugin version mismatch", -10007), //
|
||||
RESPONSE_IS_NULL("response is null", -10008),
|
||||
// Errors from Data Interface negative values
|
||||
MES_NOT_CONNECTED(ResponseDetail.MES_DATA_INTERFACE + "is not connected", -20000), //
|
||||
MES_NOT_CONFIGURED_PROPERLY(ResponseDetail.MES_DATA_INTERFACE + "is not properly configured", -20001), //
|
||||
MES_NOT_INITIALIZED(ResponseDetail.MES_DATA_INTERFACE + "is not initialized", -20002), //
|
||||
PARSED_WITH_EXCEPTION(ResponseDetail.MES_DATA_INTERFACE + "caught an exception on parsing request", -20003), //
|
||||
PROCESSED_WITH_EXCEPTION(ResponseDetail.MES_DATA_INTERFACE + "caught an exception on processing request", -20004), //
|
||||
SERIALNUMBER_NOT_ALLOWED(ResponseDetail.MES_DATA_INTERFACE + "Serialnumber not allowed", -20005), //
|
||||
PARSE_PROBLEM(ResponseDetail.MES_DATA_INTERFACE + "has a problem parsing the request", -20006), //
|
||||
NOT_SENT(ResponseDetail.MES_DATA_INTERFACE + "did not sent data", -20007), //
|
||||
MES_SERVICE_NOT_REACHABLE("iTAC.MES.Suite service is not reachable", -20008), //
|
||||
;
|
||||
|
||||
private static final String MES_DATA_INTERFACE = "iTAC.MES.Suite DataInterface ";
|
||||
|
||||
private int code;
|
||||
private String text;
|
||||
|
||||
private ResponseDetail(String text, int code) {
|
||||
this.text = text;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2008 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan.sockets;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import com.itac.mes.cogiscan.IMesServicesChannel;
|
||||
import com.itac.mes.datainterface.data.IMesServicesLog;
|
||||
import com.itac.mes.datainterface.socket.BaseIhapHandler;
|
||||
|
||||
/**
|
||||
* This handler delegates IMesService calls to a socket server for CommonSmt Interface
|
||||
*
|
||||
* @author frankp
|
||||
*
|
||||
*/
|
||||
public class IhapHandler extends BaseIhapHandler {
|
||||
|
||||
/**
|
||||
* This handler is responsible for calling all IMesServices functions at a socket server for this type.<br>
|
||||
*
|
||||
* @param host
|
||||
* the host where the server listens
|
||||
* @param port
|
||||
* the port the server listens
|
||||
* @param channelName
|
||||
* the name of the channel. As every channel has a unique name it is possible to debug server/client side
|
||||
* @param connectionStateCloseListener
|
||||
* detect wether a
|
||||
* @param classLoader
|
||||
* a classloader to override default class loader
|
||||
* @param log
|
||||
* the mesLog. if null prints direct to System.out/System.err
|
||||
* @return the reference to a base Handler
|
||||
* @throws IOException
|
||||
* thrown if no connection was established (server not available)
|
||||
*/
|
||||
public static IMesServicesChannel connect(String host, int port, String channelName,
|
||||
PropertyChangeListener connectionStateCloseListener, ClassLoader classLoader, IMesServicesLog log) throws IOException {
|
||||
// create a default connection, not bound to any type
|
||||
BaseIhapHandler handler = createHandler(host, port, channelName, connectionStateCloseListener, classLoader, log);
|
||||
|
||||
// create a proxy for a specific type (Interface)
|
||||
IMesServicesChannel mesServiceChannel = (IMesServicesChannel) Proxy.newProxyInstance(classLoader,
|
||||
new Class[] { IMesServicesChannel.class }, handler);
|
||||
|
||||
// set the channel name and transport it top server
|
||||
mesServiceChannel.setChannelName(channelName);
|
||||
return mesServiceChannel;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
BIN
interface/cogiscan/plugin/src/resources/doc/overview.pdf
Normal file
BIN
interface/cogiscan/plugin/src/resources/doc/overview.pdf
Normal file
Binary file not shown.
BIN
interface/cogiscan/plugin/src/resources/doc/overview.pptx
Normal file
BIN
interface/cogiscan/plugin/src/resources/doc/overview.pptx
Normal file
Binary file not shown.
958
interface/cogiscan/plugin/src/resources/xsd/Cogiscan.xsd
Normal file
958
interface/cogiscan/plugin/src/resources/xsd/Cogiscan.xsd
Normal file
@@ -0,0 +1,958 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
|
||||
|
||||
<xs:schema id="message" targetNamespace="cogiscan.mes.itac.com"
|
||||
xmlns="com.cogiscan.mes" xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:Q1="cogiscan.mes.itac.com"
|
||||
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0">
|
||||
<xs:annotation>
|
||||
<xs:appinfo>
|
||||
<jxb:globalBindings>
|
||||
<jxb:javaType name="java.util.Date" xmlType="xs:dateTime"
|
||||
parseMethod="com.itac.mes.cogiscan.DateAdapter.parseDate"
|
||||
printMethod="com.itac.mes.cogiscan.DateAdapter.printDate" />
|
||||
</jxb:globalBindings>
|
||||
</xs:appinfo>
|
||||
</xs:annotation>
|
||||
|
||||
<xs:complexType name="Machine">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Complete information for a machine. Used in
|
||||
iTAC.MES.Suite to find a corresponding stationNumber.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="lineName" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The line name this machine belongs to
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="machineName" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The machine name as used in Cogiscan.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="stageName" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The name (or number) of a stage. May remain
|
||||
empty if stage is not available.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lane" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If not applicable (single lane ) use a fix
|
||||
identifier (e.g. "1").
|
||||
Otherwise send an identifier for the
|
||||
lane.
|
||||
For operations which does not belong to a specific lane send the
|
||||
static value "UNDEFINED"
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lastMachineInLine" type="xs:boolean"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Set true if this machine is the last producing
|
||||
machine in a line, which is not necessarily the last
|
||||
physical machine.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="CreateContainerRequest">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Requesting information about a container from MES
|
||||
or
|
||||
advicing MES to create a material(container) in MES
|
||||
which is known
|
||||
by Cogiscan.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
|
||||
<xs:element name="container" type="Q1:Container"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>list of containers
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="operation" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>0: request material from MES
|
||||
1: create Material in MES
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:annotation>
|
||||
<xs:documentation>0: request material from MES
|
||||
1: create Material
|
||||
in MES
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:restriction base="xs:int">
|
||||
<xs:enumeration value="0"></xs:enumeration>
|
||||
<xs:enumeration value="1"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="CheckContainerRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="container" type="Q1:Container"
|
||||
minOccurs="1" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="operation" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>0: set up material (container)
|
||||
1: tear down a material (container). Errors from iTAC could be
|
||||
ignored by Cogiscan.
|
||||
2: marry a feeder with a material.
|
||||
3: divorce a material from a feeder
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:int">
|
||||
<xs:enumeration value="0"></xs:enumeration>
|
||||
<xs:enumeration value="1"></xs:enumeration>
|
||||
<xs:enumeration value="2"></xs:enumeration>
|
||||
<xs:enumeration value="3"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="ItemProducedRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="panelInfo" type="Q1:PanelInfo"
|
||||
minOccurs="0" maxOccurs="unbounded"></xs:element>
|
||||
<xs:element name="machinePlacements" type="Q1:MachinePlacement"
|
||||
minOccurs="0" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="serialNumber" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="placementRecipeName" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="orderId" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="state" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="startProduction" type="xs:dateTime"></xs:attribute>
|
||||
<xs:attribute name="endProduction" type="xs:dateTime"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="CheckContainerResponse">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="container" type="Q1:Container"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="operation" use="required">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:int">
|
||||
<xs:enumeration value="0"></xs:enumeration>
|
||||
<xs:enumeration value="1"></xs:enumeration>
|
||||
<xs:enumeration value="2"></xs:enumeration>
|
||||
<xs:enumeration value="3"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MesResponse">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Every request is answered by a response, at least containing a
|
||||
totalresult for complete Operation and
|
||||
the
|
||||
request id from its corresponding request.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:element name="errorDetails" type="Q1:ErrorDetail"
|
||||
minOccurs="0" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="requestId" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
An value identifying the call. Every response has the same requestId
|
||||
as it's corresponding request.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="totalResult" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>0 = OK 1 = NOT_OK</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:annotation>
|
||||
<xs:documentation>0 = OK 1 = NOT_OK</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:restriction base="xs:int">
|
||||
<xs:enumeration value="0"></xs:enumeration>
|
||||
<xs:enumeration value="1"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MesRequest">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Every request from Cogiscan to MES extends this
|
||||
message.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="requestId" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the request Id, to be found on both
|
||||
sides
|
||||
and both on request and response. This information
|
||||
could help on
|
||||
error analysis.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="eventDate" type="xs:dateTime" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The date and time a request is created.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="InterlockingRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="1" maxOccurs="1" nillable="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The machine (or first machine of a line)
|
||||
where
|
||||
the barcode likes to enter.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="serialNumber" type="xs:string"
|
||||
minOccurs="1" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
|
||||
|
||||
<xs:attribute name="placementRecipeName" type="xs:string"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="InterlockingResponse">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
There are several resons why a
|
||||
barcode(serialnumber) may not enter a
|
||||
machine or line. 1) internal
|
||||
processing error. 2)
|
||||
serialnumber is unknown 3) serialnumber is not
|
||||
valid at this station 4)
|
||||
serialnumber is not processed
|
||||
at previous
|
||||
workstep
|
||||
5) serialnumber is not good
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="serialNumber" type="Q1:PanelInfo"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
even if only one serialnumber was requested we
|
||||
may return a list of
|
||||
serialnumbers for a board (one
|
||||
for each
|
||||
panel)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="placementRecipeName" type="xs:string"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PanelInfoRequest">
|
||||
|
||||
<xs:complexContent>
|
||||
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="1" maxOccurs="1" nillable="false">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The machine (or first machine of a line)
|
||||
where
|
||||
the barcode likes to enter.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="serialNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The barcode or serialnumber scanned by Cogiscan
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PanelInfoResponse">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="serialNumberInfo" type="Q1:SerialnumberInfo"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
even if only one serialnumber was requested we may return a list of
|
||||
serialnumbers for a
|
||||
board (one
|
||||
for each panel)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
|
||||
<xs:attribute name="productNo" type="xs:string"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
If the serialnumber is known by iTAC this field contains the value
|
||||
of the serialnumbers
|
||||
productNo.
|
||||
If the serialnumber is unknown this field remains empty. If the
|
||||
serialnumber is
|
||||
inactive the field remains empty.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="productRevision" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
If the serialnumber is known this field contains the product
|
||||
revision (iTAC API: content of BOM
|
||||
Index). If the
|
||||
serialnumber is unknown or inactive this field remains empty.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="workorderNo" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
If the serialnumber belongs to a workorder we return the
|
||||
workorderNo. If the serialnumber is
|
||||
unknown in iTAC MES.Suite this field remains empty. If the serialnumber
|
||||
is inactive this field
|
||||
remains empty as well.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="workorderQuantity" type="xs:int"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>If the serialnumber belongs to an
|
||||
workorder this field contains the workorder quantity. If
|
||||
the
|
||||
serialnumber is
|
||||
unknown or inactive this field contains "-1"
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PlacementRecipeCheckRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="1" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>expected: first producing machine in
|
||||
line
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="placementList" type="Q1:Placement"
|
||||
minOccurs="0" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="placementRecipeName" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="setupName" type="xs:string"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PlacementRecipeCheckResponse">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="result" type="Q1:Placement"
|
||||
minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
only erroneous values are returned (wrong
|
||||
component, wrong
|
||||
designator, missing placements)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="placementRecipeName" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="setupName" type="xs:string"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="CreateContainerResponse">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
returns 0 if the container was created by mes or if
|
||||
the
|
||||
container already exists in MES, otherwise 1.
|
||||
error may
|
||||
contain a
|
||||
more detailled information.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
|
||||
|
||||
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:sequence>
|
||||
<xs:element name="container" type="Q1:Container"
|
||||
minOccurs="0" maxOccurs="unbounded"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="operation" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
0: request material from MES 1: create
|
||||
Material
|
||||
in MES
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:int">
|
||||
<xs:enumeration value="0"></xs:enumeration>
|
||||
<xs:enumeration value="1"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="HandlerPlacement">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A single placement from a container.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="designator" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The designator for a placement. Required
|
||||
information. e.g. R1 or C12.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="panelNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The panel where a placement was performed.
|
||||
Required information, value is the panel number (counting
|
||||
from 1 up) or use -1
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MachineMessageRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="1" maxOccurs="1"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="messageCode" type="xs:string"
|
||||
use="required"></xs:attribute>
|
||||
<xs:attribute name="messageStart" type="xs:dateTime"
|
||||
use="required"></xs:attribute>
|
||||
<xs:attribute name="messageStop" type="xs:dateTime"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The stop date for this message. If this
|
||||
date is
|
||||
before or equal to messageStart a default message
|
||||
time is used
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="messageDetail" type="xs:string"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The message code for the machine message.
|
||||
If this
|
||||
code is not used in iTAC this event is ignored.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MachineStatusRequest">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Used whenever a machine changes its state.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="1" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The machine descriptor.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="status" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The new status for the machine. This
|
||||
status is valid from the (inherited field) eventDate.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MachinePlacement">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A machine placement contains the complete
|
||||
inventory for one machine, as well as all handlers with its
|
||||
information.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:element name="handlerInfo" type="Q1:HandlerInfo"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>All handlers informations.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
|
||||
<xs:element name="machine" type="Q1:Machine" minOccurs="1"
|
||||
maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The machine identifier for this machines
|
||||
placements.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PanelInfo">
|
||||
<xs:annotation>
|
||||
<xs:documentation>For every single panel of a multi board iTAC
|
||||
returns the information about the single panels.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="panelName" type="xs:string"></xs:attribute>
|
||||
|
||||
<xs:attribute name="serialNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The serial number for a panel
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="panelNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The panel number of a panel</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="status" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>0 = good
|
||||
1 = rework
|
||||
2 = scrap (badmark)
|
||||
3 = unknown
|
||||
|
||||
totalresult is 0(OK) if all single serialnumbers for
|
||||
this board are
|
||||
good or
|
||||
scrap or unknown, but not all scrap
|
||||
totalresult is
|
||||
1(NOT_OK)if at least one single serialnumbers
|
||||
for this board is
|
||||
rework
|
||||
|
||||
Cogiscan should only evaluate the totalresult and may be
|
||||
displaying the
|
||||
error
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="SerialnumberInfo">
|
||||
<xs:annotation>
|
||||
<xs:documentation>For every single panel of a multi board iTAC
|
||||
returns the information about the single panels.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="serialNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The serial number for a panel
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="serialNumberPosition" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The panel number of a panel</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="status" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>0 = good
|
||||
1 = rework
|
||||
2 = scrap (badmark)
|
||||
3 = unknown
|
||||
|
||||
totalresult is 0(OK) if all single serialnumbers for
|
||||
this board are
|
||||
good or
|
||||
scrap or unknown, but not all scrap
|
||||
totalresult is
|
||||
1(NOT_OK)if at least one single serialnumbers
|
||||
for this board is
|
||||
rework
|
||||
|
||||
Cogiscan should only evaluate the totalresult and may be
|
||||
displaying the
|
||||
error
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="HandlerInfo">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A material handler (feeder or tray server) with
|
||||
information about positions for handlers, used
|
||||
container an placements from each container.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:sequence>
|
||||
<xs:annotation>
|
||||
<xs:documentation>Information about placements and used
|
||||
container for a placement.</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:element name="placement" type="Q1:HandlerPlacement"
|
||||
minOccurs="1" maxOccurs="unbounded">
|
||||
<xs:annotation>
|
||||
<xs:documentation>List of placements for this material
|
||||
Handler.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element name="container" type="Q1:Container"
|
||||
minOccurs="1" maxOccurs="1">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The container for this material handler.
|
||||
iTAC allows one container to be setup on more than one
|
||||
materialHandler
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="table" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A table number or id where a feeder is placed.
|
||||
Required for feeders.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="handlerId" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The serialnumber of a handler (feeder or tray
|
||||
server). Optional information.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="track" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A track within a table where a feeder is
|
||||
placed. Used for generating a position in iTAC.MES.Suite.
|
||||
Required information for feeders.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="division" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A sub-division if one feeder has more than one
|
||||
reel on it. Use value 1 if not appplicable.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="tower" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The position of the tower. Used for tray
|
||||
server only. Value ignored for feeders.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="level" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The used level for a tower. Used for tray
|
||||
server only. Value ignored for feeders.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="verifiedDate" type="xs:dateTime">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Date and time a container was verified.
|
||||
Optional information.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="pickAttempts" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The number of picks for material for a single
|
||||
board. It is the sum of placed and wasted components.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="placed" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The number of placed components for a single
|
||||
board. Required information.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="handlerType" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Used to identify the handler type. Could be a
|
||||
text like Feeder or Stick or Tray, or any other text.
|
||||
Optional information
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="Container">
|
||||
<xs:annotation>
|
||||
<xs:documentation>One Container containing complete container
|
||||
information. Some information is optional.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:attribute name="containerId" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The unique Id of a container (e.g. a reel or
|
||||
stick or tray). This information is always required.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="componentId" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The component Id (in iTAC: partNumber) for
|
||||
this container. Minimum required information for creating
|
||||
containers in iTAC.MES.Suite.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="initialQuantity" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Initial quantity as declared by the supplier.
|
||||
Minimum required information for creating containers in
|
||||
iTAC.MES.Suite.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="actualQuantity" type="xs:int" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>In a request this field must contain the
|
||||
actual quantity for a container. Its response message could
|
||||
contain a differing value; in this case Cogiscan should
|
||||
process
|
||||
the changed value and adjust its quantity for this
|
||||
container.
|
||||
|
||||
When a material should be created in MES and the actualQuantity differs
|
||||
from initialQuantity the actual
|
||||
quantity is
|
||||
adjusted in MES.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="supplierNumber" type="xs:string"
|
||||
use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Optional supplier number if a material should be
|
||||
created
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="supplierName" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
Optional supplier name if a material should be
|
||||
created
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="lot" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
The lot a reel belongs to. This information is
|
||||
optional, also known as a batch number
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="dateCode" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
A reels datecode as provided by a supplier.
|
||||
optional
|
||||
information.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="expirationDate" type="xs:dateTime">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The date when a container expires because of
|
||||
MSL. Use December 31 3000 if this container does never
|
||||
expires. Used for request and response.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="state" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A container state as used in iTAC.MES.Suite.
|
||||
Only used in response messages; Its content in requests
|
||||
will be ignored.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="incomingRefNumber" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>An incoming reference number for a container.
|
||||
Optional information.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="classification" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>For LEDs a lightning class, optional
|
||||
information.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
<xs:attribute name="errorText" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Detailled result for a single Container
|
||||
Request
|
||||
(information about resolving or creating container).
|
||||
Only used in a response message. Leave it null or better set it empty.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MaterialConsumedRequest">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesRequest">
|
||||
<xs:sequence>
|
||||
<xs:element name="machine" type="Q1:Machine"
|
||||
minOccurs="0" maxOccurs="1"></xs:element>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="reelId" type="xs:string"></xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="MesConfigurationResponse">
|
||||
<xs:complexContent>
|
||||
<xs:extension base="Q1:MesResponse">
|
||||
<xs:attribute name="isLineBased" type="xs:boolean"
|
||||
use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>
|
||||
true: return consolidated trace information
|
||||
for
|
||||
all machines of one line; false: return
|
||||
one trace
|
||||
information per
|
||||
machine in a line;
|
||||
if a machine is in "passthrough-mode add
|
||||
info
|
||||
about last producing machine for this
|
||||
line.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="Placement">
|
||||
<xs:attribute name="panelName" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Never empty, if unknown use 1
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="componentId" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>the component name for this placement (not the
|
||||
reelId)
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="designator" type="xs:string" use="required">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The reference designator for this placement,
|
||||
e.g.
|
||||
R12, IC1
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="resultString" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Only used as a return value.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="ErrorDetail">
|
||||
<xs:attribute name="detail" type="xs:string"></xs:attribute>
|
||||
<xs:attribute name="code" type="xs:int" use="required"></xs:attribute>
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.itac.mes.cogiscan.data.FailoverHost;
|
||||
|
||||
public class FailoverHostListTest {
|
||||
|
||||
@Test
|
||||
public void shouldReturnDefaultValues() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
assertNull("unset hostlist must return null", testee.getActiveHost());
|
||||
testee.setFailover(null);
|
||||
assertNull("null set hostlist must return null", testee.getActiveHost());
|
||||
testee.setFailover(new ArrayList<FailoverHost>());
|
||||
assertNull("empty hostlist must return null", testee.getActiveHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldReturnDefaultHost() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
testee.setFailover(failoverList);
|
||||
assertSame("hostlist with one item must return same", failoverHost, testee.getActiveHost());
|
||||
assertEquals("list have one item", 1, testee.getList().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotChangeActiveHost() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
assertSame("hostlist must return previously set host", activeHost, testee.getActiveHost());
|
||||
assertEquals("list have one item", 1, testee.getList().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveHostFromList() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
failoverList.add(activeHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
assertSame("hostlist must return previously set host", activeHost, testee.getActiveHost());
|
||||
assertEquals("list have all item", 2, testee.getList().size());
|
||||
testee.remove(activeHost);
|
||||
assertEquals("list have all item", 1, testee.size());
|
||||
assertNull("if host removed it must not remain as active host", testee.getActiveHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveHostFromList2() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
failoverList.add(activeHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
assertSame("hostlist must return previously set host", activeHost, testee.getActiveHost());
|
||||
assertEquals("list have all item", 2, testee.getList().size());
|
||||
testee.remove(failoverHost);
|
||||
assertEquals("list have all item", 1, testee.size());
|
||||
assertNotNull("if non-active host removed active host remains valid", testee.getActiveHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveHostFromListWhenSetListAgain() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
failoverList.add(activeHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
List<FailoverHost> newFailoverHosts = new ArrayList<FailoverHost>();
|
||||
newFailoverHosts.add(activeHost);
|
||||
|
||||
testee.setFailover(newFailoverHosts);
|
||||
|
||||
assertEquals("list have all item", 1, testee.size());
|
||||
assertNotNull("active host not contained in new list", testee.getActiveHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveHostFromListWhenSetListAgain2() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> newFailoverHosts = new ArrayList<FailoverHost>();
|
||||
newFailoverHosts.add(activeHost);
|
||||
newFailoverHosts.add(failoverHost);
|
||||
|
||||
testee.setFailover(newFailoverHosts);
|
||||
|
||||
assertEquals("list have all item", 2, testee.size());
|
||||
assertNotNull("active host not contained in new list", testee.getActiveHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRecognizedUnchangedList() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
testee.setFailover(failoverList);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
|
||||
testee.setFailover(failoverList);
|
||||
assertEquals("list have all item", 1, testee.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetNextHostFromList() {
|
||||
FailoverHostList testee = new FailoverHostList(null);
|
||||
|
||||
List<FailoverHost> failoverList = new ArrayList<FailoverHost>();
|
||||
FailoverHost failoverHost = new FailoverHost();
|
||||
failoverHost.setFullQualifiedHostname("fqhn");
|
||||
failoverHost.setHostname("hostname");
|
||||
failoverHost.setIpAddress("ipAddress");
|
||||
failoverHost.setPort(1234);
|
||||
failoverList.add(failoverHost);
|
||||
|
||||
FailoverHost activeHost = new FailoverHost();
|
||||
activeHost.setFullQualifiedHostname("active_fqhn");
|
||||
activeHost.setHostname("active_hostname");
|
||||
activeHost.setIpAddress("active_ipAddress");
|
||||
activeHost.setPort(1234);
|
||||
|
||||
testee.setActiveHost(activeHost);
|
||||
|
||||
List<FailoverHost> newFailoverHosts = new ArrayList<FailoverHost>();
|
||||
newFailoverHosts.add(activeHost);
|
||||
newFailoverHosts.add(failoverHost);
|
||||
testee.setFailover(newFailoverHosts);
|
||||
|
||||
testee.remove(activeHost);
|
||||
|
||||
FailoverHost host = testee.getNextFailoverHost();
|
||||
assertEquals(1, testee.size());
|
||||
assertEquals("active host not contained in new list", failoverHost.getHostname(), host.getHostname());
|
||||
|
||||
testee.remove(failoverHost);
|
||||
host = testee.getNextFailoverHost();
|
||||
assertEquals(0, testee.size());
|
||||
assertNull("no more Hosts ", host);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import static junit.framework.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import com.itac.mes.cogiscan.data.CheckContainerRequest;
|
||||
import com.itac.mes.cogiscan.data.CheckContainerResponse;
|
||||
import com.itac.mes.cogiscan.data.MesRequest;
|
||||
import com.itac.mes.cogiscan.data.MesResponse;
|
||||
|
||||
public class MesServicesTest {
|
||||
|
||||
@Test
|
||||
public void shouldNotStartWithInvalidPort() {
|
||||
MesServices testee = new MesServices("localhost", 100);
|
||||
assertNotNull(testee);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckHostnameValid() {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
assertFalse(testee.isHostNameValid(null));
|
||||
assertFalse(testee.isHostNameValid(""));
|
||||
assertTrue(testee.isHostNameValid("localhost"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCheckPortValid() {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
for (int i = 0; i < 1023; i++) {
|
||||
assertFalse("" + i, testee.isPortValid(i));
|
||||
}
|
||||
|
||||
for (int i = 1024; i < 49150; i++) {
|
||||
assertTrue("" + i, testee.isPortValid(i));
|
||||
}
|
||||
|
||||
for (int i = 49151; i < 65535; i++) {
|
||||
assertFalse("" + i, testee.isPortValid(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = CogiscanException.class)
|
||||
public void shouldCheckPrecond0() throws CogiscanException {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
|
||||
testee.checkPreconditions(null, null);
|
||||
}
|
||||
|
||||
@Test(expected = CogiscanException.class)
|
||||
public void shouldCheckPrecond1() throws CogiscanException {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
MesRequest request = new MesRequest();
|
||||
|
||||
testee.checkPreconditions(null, request);
|
||||
}
|
||||
|
||||
@Test(expected = CogiscanException.class)
|
||||
public void shouldCheckPrecond2() throws CogiscanException {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
MesResponse response = new MesResponse();
|
||||
MesRequest request = new MesRequest();
|
||||
request.setRequestId(-5);
|
||||
testee.checkPreconditions(response, request);
|
||||
assertTrue(request.getRequestId() >= 0);
|
||||
assertTrue(request.getRequestId() == response.getRequestId());
|
||||
assertNotNull(request.getEventDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldxxx() throws CogiscanException {
|
||||
MesServices testee = new MesServices("localhost", 10000);
|
||||
MesServices spyTestee = Mockito.spy(testee);
|
||||
IMesServices mockMesServices = mock(IMesServices.class);
|
||||
CheckContainerResponse response = new CheckContainerResponse();
|
||||
when(mockMesServices.mesCheckContainer(Mockito.any(CheckContainerRequest.class))).thenReturn(response);
|
||||
when(spyTestee.getFailoverProxy()).thenReturn(mockMesServices);
|
||||
|
||||
when(spyTestee.isActive()).thenReturn(true);
|
||||
|
||||
CheckContainerRequest checkContainerRequest = new CheckContainerRequest();
|
||||
CheckContainerResponse r = spyTestee.mesCheckContainer(checkContainerRequest);
|
||||
assertNotNull(r);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
|
||||
*
|
||||
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
|
||||
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
|
||||
* without the written permission of iTAC Software AG.
|
||||
*/
|
||||
package com.itac.mes.cogiscan;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class RequestIdGeneratorTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
RequestIdGenerator.MAX_REQUEST_ID = 100;
|
||||
|
||||
Set<Integer> idSet = new HashSet<Integer>();
|
||||
|
||||
RequestIdGenerator testee = new RequestIdGenerator();
|
||||
for (int i = 0; i < 200; i++) {
|
||||
idSet.add(testee.getNextId());
|
||||
}
|
||||
assertEquals(100, idSet.size());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user