package rocks.inspectit.shared.cs.ci.business.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import org.codehaus.jackson.annotate.JsonIgnore;
import rocks.inspectit.shared.all.exception.BusinessException;
import rocks.inspectit.shared.all.exception.enumeration.BusinessContextErrorCodeEnum;
import rocks.inspectit.shared.cs.ci.business.expression.AbstractExpression;
import rocks.inspectit.shared.cs.ci.business.expression.impl.BooleanExpression;
/**
* Configuration element defining an application context.
*
* @author Alexander Wert
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "applicaction")
public class ApplicationDefinition implements IMatchingRuleProvider {
/**
* The name of the default application.
*/
public static final String UNKNOWN_APP = "Unknown Application";
/**
* The default identifier.
*/
public static final int DEFAULT_ID = 0;
/**
* Default application definition that matches any data. Therefore {@link BooleanExpression}
* with true is used.
*/
public static final ApplicationDefinition DEFAULT_APPLICATION_DEFINITION = new ApplicationDefinition(ApplicationDefinition.DEFAULT_ID, UNKNOWN_APP, new BooleanExpression(true, true));
/**
* Identifier of the application. Needs to be unique!
*/
@XmlAttribute(name = "id", required = true)
private int id = (int) UUID.randomUUID().getMostSignificantBits();
/**
* Name of the application.
*/
@XmlAttribute(name = "name", required = true)
private String applicationName;
/**
* Description.
*/
@XmlAttribute(name = "description", required = false)
private String description;
/**
* Revision. Server for version control and updating control.
*/
@JsonIgnore
@XmlAttribute(name = "revision")
private Integer revision = Integer.valueOf(1);
/**
* Rule definition for matching measurement data to applications.
*
* Default Matching rule should not match any data, therefore {@link BooleanExpression} with
* false is used.
*/
@XmlElementRef
private AbstractExpression matchingRuleExpression = new BooleanExpression(false);
/**
* Business transaction definitions.
*/
@JsonIgnore
@XmlElementWrapper(name = "business-transactions")
@XmlElementRef(type = BusinessTransactionDefinition.class)
private final List<BusinessTransactionDefinition> businessTransactionDefinitions = new ArrayList<BusinessTransactionDefinition>();
/**
* Default constructor.
*/
public ApplicationDefinition() {
}
/**
* Constructor.
*
* @param applicationName
* name of the application
*/
public ApplicationDefinition(String applicationName) {
this.applicationName = applicationName;
}
/**
* Constructor.
*
* @param id
* unique identifier to use for this {@link ApplicationDefinition}
* @param applicationName
* name of the application
* @param matchingRuleExpression
* matching rule to use for recognition of this application
*/
public ApplicationDefinition(int id, String applicationName, AbstractExpression matchingRuleExpression) {
this(applicationName);
this.matchingRuleExpression = matchingRuleExpression;
this.id = id;
}
/**
* Returns the name of the application.
*
* @return Returns the name of the application
*/
public String getApplicationName() {
return applicationName;
}
/**
* Sets the name of the application.
*
* @param applicationName
* New value for the name of the application.
*/
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
/**
* {@inheritDoc}
*/
@Override
public AbstractExpression getMatchingRuleExpression() {
return matchingRuleExpression;
}
/**
* {@inheritDoc}
*/
@Override
public void setMatchingRuleExpression(AbstractExpression matchingRuleExpression) {
this.matchingRuleExpression = matchingRuleExpression;
}
/**
* Returns an unmodifiable list of all {@link BusinessTransactionDefinition} instances known in
* this application definition.
*
* @return unmodifiable list of all {@link BusinessTransactionDefinition} instances known in
* this application definition
*/
public List<BusinessTransactionDefinition> getBusinessTransactionDefinitions() {
List<BusinessTransactionDefinition> allbusinessTxDefinitions = new ArrayList<BusinessTransactionDefinition>(businessTransactionDefinitions);
allbusinessTxDefinitions.add(BusinessTransactionDefinition.DEFAULT_BUSINESS_TRANSACTION_DEFINITION);
return Collections.unmodifiableList(allbusinessTxDefinitions);
}
/**
* Retrieves the {@link BusinessTransactionDefinition} with the given identifier.
*
* @param id
* unique id identifying the business transaction to retrieve
* @return Return the {@link BusinessTransactionDefinition} with the given id, or null if no
* {@link BusinessTransactionDefinition} with the passed id could be found.
*
* @throws BusinessException
* if no {@link BusinessTransactionDefinition} with the given identifier exists.
*/
public BusinessTransactionDefinition getBusinessTransactionDefinition(int id) throws BusinessException {
if (id == BusinessTransactionDefinition.DEFAULT_ID) {
return BusinessTransactionDefinition.DEFAULT_BUSINESS_TRANSACTION_DEFINITION;
}
for (BusinessTransactionDefinition businessTxDef : businessTransactionDefinitions) {
if (businessTxDef.getId() == id) {
return businessTxDef;
}
}
throw new BusinessException("Retrieve business transaction with id '" + id + "'.", BusinessContextErrorCodeEnum.UNKNOWN_BUSINESS_TRANSACTION);
}
/**
* Adds business transaction definition to the application definition.
*
* @param businessTransactionDefinition
* {@link BusinessTransactionDefinition} instance to add
* @throws BusinessException
* If the application definition already contains a business transaction with same
* identifier.
*/
public void addBusinessTransactionDefinition(BusinessTransactionDefinition businessTransactionDefinition) throws BusinessException {
addBusinessTransactionDefinition(businessTransactionDefinition, businessTransactionDefinitions.size());
}
/**
* Adds business transaction definition to the application definition. Inserts it to the list
* before the element with the passed index.
*
* @param businessTransactionDefinition
* {@link BusinessTransactionDefinition} instance to add
* @param insertBeforeIndex
* insert before this index
* @throws BusinessException
* If the application definition already contains a business transaction with same
* identifier or the insertBeforeIndex is not valid.
*/
public void addBusinessTransactionDefinition(BusinessTransactionDefinition businessTransactionDefinition, int insertBeforeIndex) throws BusinessException {
if (businessTransactionDefinition == null) {
throw new BusinessException("Adding business transaction 'null'.", BusinessContextErrorCodeEnum.UNKNOWN_BUSINESS_TRANSACTION);
} else if (businessTransactionDefinitions.contains(businessTransactionDefinition)) {
throw new BusinessException(
"Adding business transaction " + businessTransactionDefinition.getBusinessTransactionDefinitionName() + " with id " + businessTransactionDefinition.getId() + ".",
BusinessContextErrorCodeEnum.DUPLICATE_ITEM);
} else if ((insertBeforeIndex < 0) || (insertBeforeIndex > businessTransactionDefinitions.size())) {
throw new BusinessException("Adding business transaction " + businessTransactionDefinition.getBusinessTransactionDefinitionName() + " with id " + businessTransactionDefinition.getId()
+ " at index " + insertBeforeIndex + ".", BusinessContextErrorCodeEnum.INVALID_MOVE_OPRATION);
} else {
businessTransactionDefinitions.add(insertBeforeIndex, businessTransactionDefinition);
}
}
/**
* Deletes the {@link BusinessTransactionDefinition} from the application definition.
*
* @param businessTransactionDefinition
* {@link BusinessTransactionDefinition} to delete
*
* @return Returns true if the application definition contained the business transaction
*/
public boolean deleteBusinessTransactionDefinition(BusinessTransactionDefinition businessTransactionDefinition) {
return businessTransactionDefinitions.remove(businessTransactionDefinition);
}
/**
* Moves the {@link BusinessTransactionDefinition} to a different position specified by the
* index parameter.
*
* @param businessTransactionDefinition
* {@link BusinessTransactionDefinition} to move
* @param index
* position to move the {@link BusinessTransactionDefinition} to
* @throws BusinessException
* If the moving the {@link BusinessTransactionDefinition} fails.
*/
public void moveBusinessTransactionDefinition(BusinessTransactionDefinition businessTransactionDefinition, int index) throws BusinessException {
if ((index < 0) || (index >= businessTransactionDefinitions.size())) {
throw new BusinessException("Moving business transaction to index " + index + ".", BusinessContextErrorCodeEnum.INVALID_MOVE_OPRATION);
}
int currentIndex = businessTransactionDefinitions.indexOf(businessTransactionDefinition);
if (currentIndex < 0) {
throw new BusinessException("Moving business transaction to index " + index + ".", BusinessContextErrorCodeEnum.UNKNOWN_BUSINESS_TRANSACTION);
}
if (index != currentIndex) {
BusinessTransactionDefinition definitionToMove = businessTransactionDefinitions.remove(currentIndex);
businessTransactionDefinitions.add(index, definitionToMove);
}
}
/**
* {@inheritDoc}
*/
@JsonIgnore
@Override
public boolean isChangeable() {
return getId() != DEFAULT_ID;
}
/**
* Returns the unique identifier of this application definition.
*
* @return Returns the unique identifier of this application definition.
*/
public int getId() {
return id;
}
/**
* Returns the description text.
*
* @return Returns the description text.
*/
public String getDescription() {
return description;
}
/**
* Sets the description text.
*
* @param description
* New value for the description text.
*/
public void setDescription(String description) {
this.description = description;
}
/**
* Gets {@link #revision}.
*
* @return {@link #revision}
*/
public int getRevision() {
return revision.intValue();
}
/**
* Sets {@link #revision}.
*
* @param revision
* New value for {@link #revision}
*/
public void setRevision(int revision) {
this.revision = Integer.valueOf(revision);
}
/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = (prime * result) + id;
return result;
}
/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ApplicationDefinition other = (ApplicationDefinition) obj;
if (id != other.id) {
return false;
}
return true;
}
}