package archmapper.main.model;
import java.util.ArrayList;
import java.util.List;
import archmapper.main.model.architecture.Component;
import archmapper.main.model.architecture.Configuration;
import archmapper.main.model.architecture.Connector;
import archmapper.main.model.architecture.Port;
import archmapper.main.model.architecture.Role;
import archmapper.main.model.archmapping.ArchitectureMapping;
import archmapper.main.model.archmapping.ComponentMapping;
import archmapper.main.model.archmapping.ConnectorMapping;
import archmapper.main.model.archmapping.ImplementableArchitectureElementMapping;
import archmapper.main.model.archmapping.ImplementationArtifactDefinition;
import archmapper.main.model.archmapping.PortMapping;
import archmapper.main.model.stylemapping.ComponentTypeMapping;
import archmapper.main.model.stylemapping.ConnectorTypeMapping;
import archmapper.main.model.stylemapping.ImplementableTypeMapping;
import archmapper.main.model.stylemapping.ImplementationArtifactType;
import archmapper.main.model.stylemapping.PortTypeMapping;
import archmapper.main.model.stylemapping.RoleTypeMapping;
import archmapper.main.model.stylemapping.StyleMapping;
/**
* This class checks the mapping files/models for consistency with each other
* and with an architecture. Warnings are gathered in lists of Strings,
* according to their occurence and severity.
*
* @author mg
*
*/
public class MappingFileChecker {
protected List<String> archMappingWarnings = new ArrayList<String>();
protected List<String> archMappingErrors = new ArrayList<String>();
protected List<String> styleMappingWarnings = new ArrayList<String>();
protected List<String> styleMappingErrors = new ArrayList<String>();
protected Configuration arch;
protected ArchitectureMapping archMapping;
protected StyleMapping styleMapping;
public MappingFileChecker(Configuration arch, ArchitectureMapping archMapping,
StyleMapping styleMapping) {
this.arch = arch;
this.archMapping = archMapping;
this.styleMapping = styleMapping;
}
/**
* Executes all checks are defined in this class
*
*/
public void checkEverything() {
checkUnusedTypesInStyleMapping();
checkInvalidNamesInArchMapping();
checkIfNonOptionalTypesArePresent();
}
public void checkArchitectureMappingWarnings() {
checkUnmappedComponentsInArchMapping();
}
public void checkArchitectureMappingErrors() {
checkInvalidNamesInArchMapping();
checkIfNonOptionalTypesArePresent();
}
public void checkUnusedTypesInStyleMapping() {
if (styleMapping == null) {
styleMappingErrors.add("There is no style mapping defined.");
return;
}
for (ComponentTypeMapping compTypeMapping : styleMapping.getComponentTypeMapping()) {
if (arch.getComponentsWithType(compTypeMapping.getTypeName()).size() == 0) {
styleMappingWarnings.add("A component with the style type '"+ compTypeMapping.getTypeName()+
"' does not exist in the architecture.");
}
}
for (ConnectorTypeMapping connTypeMapping : styleMapping.getConnectorTypeMapping()) {
if (arch.getConnectorsWithType(connTypeMapping.getTypeName()).size() == 0) {
styleMappingWarnings.add("A connector with the style type '"+ connTypeMapping.getTypeName()+
"' does not exist in the architecture.");
}
}
for (RoleTypeMapping roleTypeMapping : styleMapping.getRoleTypeMapping()) {
boolean present = false;
for (Connector conn : arch.getConnectors()) {
for (Role role : conn.getRoles()) {
if (roleTypeMapping.getTypeName().equals(role.getStyleType())) {
present = true;
}
}
}
if (!present) {
styleMappingWarnings.add("A role with the style type '"+
roleTypeMapping.getTypeName() + "' does not exist in the architecture.");
}
}
for (PortTypeMapping portTypeMapping : styleMapping.getPortTypeMapping()) {
boolean present = false;
for (Component comp : arch.getComponents()) {
for (Port port : comp.getPorts()) {
if (portTypeMapping.getTypeName().equals(port.getStyleType())) {
present = true;
}
}
}
if (!present) {
styleMappingWarnings.add("A port with the style type '"+
portTypeMapping.getTypeName()+ "' does not exist in the architecture.");
}
}
}
/**
* Checks if all elements from the architecture have a mapping in the
* architecture mapping file.
*
*/
public void checkUnmappedComponentsInArchMapping() {
for (Component comp : arch.getComponents()) {
ComponentMapping compMapping = archMapping.getComponentMapping(comp.getName());
if (compMapping == null) {
archMappingWarnings.add("The component '"+ comp.getName() +
"' is not mapped in the architecture mapping.");
}
}
}
public void checkInvalidNamesInArchMapping() {
if (archMapping != null) {
for (ComponentMapping compMapping : archMapping.getComponentMapping()) {
if (arch.getComponentByName(compMapping.getComponentName()) == null) {
archMappingErrors.add("A component with the name '"+ compMapping.getComponentName()+
"' does not exist in the architecture.");
} else {
checkInvalidNamesInComponentAndConnectorMappings(compMapping);
checkInvalidPortNames(compMapping.getPortMapping());
}
}
for (ConnectorMapping connMapping : archMapping.getConnectorMapping()) {
if (arch.getConnectorByName(connMapping.getConnectorName()) == null) {
archMappingErrors.add("A connector with the name '"+ connMapping.getConnectorName()+
"' does not exist in the architecture.");
} else {
checkInvalidNamesInComponentAndConnectorMappings(connMapping);
}
}
}
}
protected void checkInvalidNamesInComponentAndConnectorMappings(ImplementableArchitectureElementMapping mapping) {
ImplementableTypeMapping typeMapping = null;
if (styleMapping != null) {
if (mapping instanceof ComponentMapping) {
Component comp = arch.getComponentByName(mapping.getName());
typeMapping = styleMapping.getComponentType(comp.getStyleType());
} else {
Connector conn = arch.getConnectorByName(mapping.getName());
typeMapping = styleMapping.getConnectorTypeMapping(conn.getStyleType());
}
}
checkInvalidTypesInImplementationArtifactDefinitions(mapping.getClassDefinition(),
typeMapping);
checkInvalidTypesInImplementationArtifactDefinitions(mapping.getInterfaceDefinition(),
typeMapping);
checkInvalidTypesInImplementationArtifactDefinitions(mapping.getFileDefinition(),
typeMapping);
}
/**
* Checks if there are implementation artifact definitions that have types which
* are not defined in the style mapping.
*
* @param defs
* @param typeMapping
*/
protected void checkInvalidTypesInImplementationArtifactDefinitions(List<? extends ImplementationArtifactDefinition> defs,
ImplementableTypeMapping typeMapping) {
for (ImplementationArtifactDefinition implDef : defs) {
String artifactType = implDef.getClass().getSimpleName();
String type = implDef.getType();
if (type != null) {
if (typeMapping == null) {
archMappingErrors.add("A "+ artifactType +" type was defined ("+ type +") although there is no style "+
"mapping for the containing "+ implDef.getParent().getName()+ ".");
} else {
ImplementationArtifactType artType = typeMapping.getImplementationArtifactType(type);
if (artType == null) {
archMappingErrors.add("A "+ artifactType +" type with the type name "+ type +
" does not exist in the style mapping.");
}
}
}
}
}
protected void checkInvalidPortNames(List<PortMapping> portMappings) {
for (PortMapping portMapping : portMappings) {
ComponentMapping compMapping = portMapping.getParent();
Component comp = arch.getComponentByName(compMapping.getComponentName());
if (comp.getPortByName(portMapping.getPortName()) == null) {
archMappingErrors.add("The port "+ portMapping.getPortName() + " of the component "+
comp.getName() + " does not exist in the architecture.");
}
}
}
/**
* Checks if non-optional implementation artifact types from the style mapping
* are really instantiated in the architecture mapping.
*
*/
public void checkIfNonOptionalTypesArePresent() {
if (styleMapping == null) {
return;
}
for (ImplementableTypeMapping typeMapping : styleMapping.getAllImplementableTypeMappings()) {
List<String> archElementNames = new ArrayList<String>();
if (typeMapping instanceof ConnectorTypeMapping) {
for (Connector conn : arch.getConnectors()) {
if (conn.getStyleType() != null && conn.getStyleType().equals(typeMapping.getTypeName())) {
archElementNames.add(conn.getName());
}
}
} else {
for (Component comp : arch.getComponents()) {
if (comp.getStyleType() != null && comp.getStyleType().equals(typeMapping.getTypeName())) {
archElementNames.add(comp.getName());
}
}
}
for (ImplementationArtifactType artType : typeMapping.getAllImplementationArtifactTypes()) {
if (!artType.isOptional()) {
for (ImplementableArchitectureElementMapping archElemMapping : archMapping.getAllImplementableArchitectureElementMappings()) {
if (archElementNames.contains(archElemMapping.getName())) {
if (archElemMapping.getImplementationArtifactDefinitionOfType(
artType.getTypeName()).size() == 0) {
archMappingErrors.add("The non-optional "+ artType.getClass().getSimpleName() +
" '"+ artType.getTypeName() +"' has no instantiation in the " +
archElemMapping.getClass().getSimpleName()+ " '"+ archElemMapping.getName()+ "'.");
}
}
}
}
}
}
}
public List<String> getAllWarningsAndErrors() {
List<String> allWarnings = new ArrayList<String>();
allWarnings.addAll(archMappingWarnings);
allWarnings.addAll(styleMappingWarnings);
allWarnings.addAll(styleMappingErrors);
allWarnings.addAll(archMappingErrors);
return allWarnings;
}
public List<String> getArchMappingErrors() {
return archMappingErrors;
}
public List<String> getArchMappingWarnings() {
return archMappingWarnings;
}
public List<String> getStyleMappingErrors() {
return styleMappingErrors;
}
public List<String> getStyleMappingWarnings() {
return styleMappingWarnings;
}
/**
* Clears the list of warnings and errors. Used for
* testing purposed only.
*
*/
public void clearAllWarningsAndErrors() {
archMappingErrors.clear();
archMappingWarnings.clear();
styleMappingErrors.clear();
styleMappingWarnings.clear();
}
}