initialize

This commit is contained in:
Pruefer
2025-06-06 09:15:13 +02:00
commit fa7c2730f1
5817 changed files with 1339670 additions and 0 deletions

View 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>

View File

@@ -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;
}
}

View File

@@ -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";
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View 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>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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());
}
}