/**
* Copyright 2014 SAP AG
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.spotter.ext.detection.blob;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A component is a participant of the messaging procedure.
*
* @author Alexander Wert
*
*/
public class Component implements Serializable {
private static final double _100_PERCENT = 100D;
/** */
private static final long serialVersionUID = 4873965184317389096L;
private List<String> componentsWhoSentToMe = new ArrayList<String>();
// LOCAL FIELDS
private String id;
private double totalMessageSentDuration;
private double longestMessageSentDuration;
private double shortestMessageSentDuration;
private double averageMessageSentDuration;
private long messagesReceived = 0;
private long messagesSent = 0;
private ProcessedData parentContainer;
private Map<String, Long> sendToCountMap = new HashMap<String, Long>();
private Map<String, Double> sendToDurationMap = new HashMap<String, Double>();
private String[] stackTrace;
Component(ProcessedData parent, String componentId) {
parentContainer = parent;
id = componentId;
}
/**
* Adds id of component which received messages from this component.
*
* @param receiverId
* id of the receiver component
*/
public void addSendMessageTo(String receiverId) {
if (sendToCountMap.containsKey(receiverId)) {
sendToCountMap.put(receiverId, sendToCountMap.get(receiverId) + 1L);
} else {
sendToCountMap.put(receiverId, 1L);
}
}
/**
* Adds id of component which received messages from this component.
*
* @param receiverId
* id of the receiver component
* @param duration
* duration to add
*/
public void addSendMessageToDuration(String receiverId, double duration) {
if (sendToDurationMap.containsKey(receiverId)) {
sendToDurationMap.put(receiverId, sendToDurationMap.get(receiverId) + duration);
} else {
sendToDurationMap.put(receiverId, duration);
}
}
/**
*
* @return average percentage as target
*/
public double getAveragePercentageAsTarget() {
double sum = 0;
long cCount = 0;
for (String componentId : componentsWhoSentToMe) {
if (componentId.equals(id)) {
continue;
}
cCount++;
sum += parentContainer.getComponent(componentId).getPercentageSendToComponent(id);
}
return sum / cCount;
}
/**
* Adds a component which sent a message to this component.
*
* @param clientId
* id of the component who sent a message to this component
*/
public void addComponentWhoSentToMe(String clientId) {
if (!componentsWhoSentToMe.contains(clientId)) {
componentsWhoSentToMe.add(clientId);
}
}
/**
* Returns number of messages send per millisecond.
*
* @return number of messages send per millisecond.
*/
public double getMessageSendRate() {
return messagesSent / parentContainer.getTotalExperimentDuration();
}
/**
* Returns the percentage of messages which was received by this component.
*
* @return the percentage of messages which was received by this component.
*/
public double getPercentageMessageReceived() {
return _100_PERCENT / parentContainer.getTotalMessagesReceived() * messagesReceived;
}
/**
* Returns the percentage of messages which was sent by this component.
*
* @return the percentage of messages which was sent by this component.
*/
public double getPercentageMessageSend() {
return _100_PERCENT / parentContainer.getTotalMessagesSent() * messagesSent;
}
/**
*
* @param componentId
* id of component of interest
* @return percentage of messages send to the given component
*/
public double getPercentageSendToComponent(String componentId) {
if (!sendToCountMap.containsKey(componentId)) {
return 0;
}
return _100_PERCENT / messagesSent * sendToCountMap.get(componentId);
}
/**
*
*
* @return messages received per millisecond.
*/
public double getMessageReceiveRate() {
return messagesReceived / parentContainer.getTotalExperimentDuration();
}
/**
* Returns a sorted list with client-ids. Descending order according to the
* number of messages sent.
*
* @return sorted list of messages sent
*/
public List<String> getSortedMessagesSendToList() {
List<String> returnList = new ArrayList<String>();
returnList.addAll(sendToCountMap.keySet());
Collections.sort(returnList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return (int) (sendToCountMap.get(o2) - sendToCountMap.get(o1));
}
});
return returnList;
}
/**
* Increase the received message count.
*/
public void increaseMessageReceived() {
messagesReceived++;
parentContainer.increaseMessageReceivedCount();
}
/**
* Increase the sent message count.
*/
public void increaseMessageSent() {
messagesSent++;
parentContainer.increaseMessageSentCount();
}
/**
* Sets the stackTrace field.
*
* @param stackTrace
* string representation of the stacktrace
*/
public void setStackTrace(String stackTrace) {
this.stackTrace = stackTrace.split("#");
}
@Override
public String toString() {
return toString(false);
}
/**
* Creates a string for the component.
*
* @param sendList
* if send list exists
* @return string representation of this component
*/
public String toString(boolean sendList) {
StringBuilder builder = new StringBuilder();
builder.append("ID: ");
builder.append(id);
builder.append("\n\tMESSAGES SEND *************************************\n\t\tTotal:\t");
builder.append(messagesSent);
builder.append("\n\t\tPct.:\t");
DecimalFormat dcFormat = new DecimalFormat("#0.00");
builder.append(dcFormat.format(getPercentageMessageSend()));
builder.append(" %\n\t\tRate:\t");
builder.append(getMessageSendRate());
builder.append(" Msg/ms\n\t\tMESSAGE SEND TO\n");
if (sendList) {
for (String key : getSortedMessagesSendToList()) {
builder.append("\t\t\t");
builder.append(sendToCountMap.get(key));
builder.append("|");
builder.append(dcFormat.format(getPercentageSendToComponent(key)));
builder.append("% -> ");
builder.append(key);
builder.append("\n");
}
}
builder.append("\tMESSAGES RECEIVED *********************************\n\t\tTotal:\t");
builder.append(messagesReceived);
builder.append("\n\t\tPct.:\t");
builder.append(dcFormat.format(getPercentageMessageReceived()));
builder.append(" %\n\t\tRate:\t");
builder.append(getMessageReceiveRate());
builder.append(" Msg/ms\n\t\tAvg target:\t");
builder.append(dcFormat.format(getAveragePercentageAsTarget()));
builder.append(" %\n\tSENT MSG DURRATION UNTIL RECEIVE ******************\n\t\tMessages totalTime:\t");
builder.append(totalMessageSentDuration);
builder.append("ms\n\t\tMessages avgTime:\t");
builder.append(averageMessageSentDuration);
builder.append("ms\n\t\tMessages longest:\t");
builder.append(longestMessageSentDuration);
builder.append("ms\n\t\tMessages shortest:\t");
builder.append(shortestMessageSentDuration);
builder.append("ms\n\tSTACKTRACE\n");
for (int i = 0; i < stackTrace.length; i++) {
for (int x = 0; x < i + 1; x++) {
builder.append("\t");
}
builder.append(stackTrace[stackTrace.length - 1 - i]);
builder.append("\n");
}
return builder.toString();
}
/**
* @return the componentsWhoSentToMe
*/
public List<String> getComponentsWhoSentToMe() {
return componentsWhoSentToMe;
}
/**
* @param componentsWhoSentToMe
* the componentsWhoSentToMe to set
*/
public void setComponentsWhoSentToMe(List<String> componentsWhoSentToMe) {
this.componentsWhoSentToMe = componentsWhoSentToMe;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @param id
* the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* @return the totalMessageSentDuration
*/
public double getTotalMessageSentDuration() {
return totalMessageSentDuration;
}
/**
* @param totalMessageSentDuration
* the totalMessageSentDuration to set
*/
public void setTotalMessageSentDuration(double totalMessageSentDuration) {
this.totalMessageSentDuration = totalMessageSentDuration;
}
/**
* @return the longestMessageSentDuration
*/
public double getLongestMessageSentDuration() {
return longestMessageSentDuration;
}
/**
* @param longestMessageSentDuration
* the longestMessageSentDuration to set
*/
public void setLongestMessageSentDuration(double longestMessageSentDuration) {
this.longestMessageSentDuration = longestMessageSentDuration;
}
/**
* @return the shortestMessageSentDuration
*/
public double getShortestMessageSentDuration() {
return shortestMessageSentDuration;
}
/**
* @param shortestMessageSentDuration
* the shortestMessageSentDuration to set
*/
public void setShortestMessageSentDuration(double shortestMessageSentDuration) {
this.shortestMessageSentDuration = shortestMessageSentDuration;
}
/**
* @return the averageMessageSentDuration
*/
public double getAverageMessageSentDuration() {
return averageMessageSentDuration;
}
/**
* @param averageMessageSentDuration
* the averageMessageSentDuration to set
*/
public void setAverageMessageSentDuration(double averageMessageSentDuration) {
this.averageMessageSentDuration = averageMessageSentDuration;
}
/**
* @return the messagesReceived
*/
public long getMessagesReceived() {
return messagesReceived;
}
/**
* @param messagesReceived
* the messagesReceived to set
*/
public void setMessagesReceived(long messagesReceived) {
this.messagesReceived = messagesReceived;
}
/**
* @return the messagesSent
*/
public long getMessagesSent() {
return messagesSent;
}
/**
* @param messagesSent
* the messagesSent to set
*/
public void setMessagesSent(long messagesSent) {
this.messagesSent = messagesSent;
}
/**
* @return the sendToCountMap
*/
public Map<String, Long> getSendToCountMap() {
return sendToCountMap;
}
/**
* @param sendToCountMap
* the sendToCountMap to set
*/
public void setSendToCountMap(Map<String, Long> sendToCountMap) {
this.sendToCountMap = sendToCountMap;
}
/**
* @return the stackTrace
*/
public String[] getStackTrace() {
return stackTrace;
}
/**
* @param stackTrace
* the stackTrace to set
*/
public void setStackTrace(String[] stackTrace) {
this.stackTrace = stackTrace;
}
/**
* @return the sendToDurationMap
*/
public Map<String, Double> getSendToDurationMap() {
return sendToDurationMap;
}
/**
* @param sendToDurationMap
* the sendToDurationMap to set
*/
public void setSendToDurationMap(Map<String, Double> sendToDurationMap) {
this.sendToDurationMap = sendToDurationMap;
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Component other = (Component) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
return true;
}
}