package archmapper.main.model;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import archmapper.main.Preferences;
import archmapper.main.exceptions.ArchMapperException;
import archmapper.main.exceptions.NoArchitectureException;
import archmapper.main.exceptions.NoArchitectureMappingException;
import archmapper.main.model.architecture.Configuration;
import archmapper.main.model.architecture.Connector;
import archmapper.main.model.architecture.Role;
import archmapper.main.model.archmapping.ArchitectureMapping;
import archmapper.main.model.archmapping.ArchitectureMappingDAO;
import archmapper.main.model.stylemapping.RoleTypeMapping;
import archmapper.main.model.stylemapping.StyleMapping;
import archmapper.main.model.stylemapping.StyleMappingDAO;
public class ArchitectureMappingModel {
private Configuration conf;
private StyleMapping styleMapping;
private ArchitectureMapping archMapping;
private IProject project;
/**
* Creates a new Instance of this class. Creates all models
* that are needed for architecture mapping: architecture model,
* architecture mapping and style mapping. Takes the settings
* for the creation of the models from the project preferences.
*
* @param project
*/
public ArchitectureMappingModel(IProject project) {
this.project = project;
Preferences pref = new Preferences(project);
IFile adlFile = pref.getArchitectureFile();
if (adlFile == null) {
throw new NoArchitectureException();
}
conf = getArchitectureFromExtensionPoint(adlFile);
// now, the mapping files have to be read...
IFile archMappingFile = pref.getArchitectureMappingFile();
if (pref.isArchitectureMappingPresent() && (
archMappingFile == null || !archMappingFile.exists())) {
throw new NoArchitectureMappingException();
}
if (archMappingFile != null && archMappingFile.exists()) {
archMapping = ArchitectureMappingDAO.read(archMappingFile.getLocation().toOSString());
archMapping.setMappingFile(archMappingFile);
} else {
// if no architecture mapping should be used, create a new one
archMapping = new ArchitectureMapping();
}
styleMapping = loadStyleMapping(archMappingFile, archMapping.getStyleMappingFile(),
conf.getArchitecturalStyle(), archMapping.getStyleMappingName());
if (styleMapping == null) {
// if no style mapping should be used, create a new one...
styleMapping = new StyleMapping();
}
setRoleDirectionInArchitecture(false);
}
public ArchitectureMappingModel(Configuration conf, StyleMapping styleMapping,
ArchitectureMapping archMapping) {
this.styleMapping = styleMapping;
this.archMapping = archMapping;
this.conf = conf;
setRoleDirectionInArchitecture(false);
}
public static StyleMapping loadStyleMapping(IFile archMappingFile,
String styleMappingFilename, String styleName, String styleMappingName) {
StyleMapping styleMapping = null;
if (styleMappingFilename != null && archMappingFile != null) {
IFile styleMappingFile = archMappingFile.getParent().getFile(new Path(styleMappingFilename));
if (styleMappingFile.exists()) {
styleMapping = StyleMappingDAO.read(styleMappingFile.getLocation().toOSString());
styleMapping.setMappingFile(styleMappingFile);
}
}
if (styleMapping == null) {
styleMapping = getStyleMappingFromExtensionPoint(styleMappingName, null);
if (styleMapping == null) {
styleMapping = getStyleMappingFromExtensionPoint(null, styleName);
}
}
return styleMapping;
}
/**
* Sets the role direction in the architecture file according to
* the settings in the style mapping. This method is called in the
* constructor. It should only be called externally if the architecture
* or the style mapping changed after this class has been created.
*
* @param overwriteArchitecture If this parameter is set, then all role
* direction settings from the architecture are overwritten
* by the settings in the style. Otherwise, existing settings in
* the architecture are preserved.
*
*/
public void setRoleDirectionInArchitecture(boolean overwriteArchitecture) {
for (Connector conn : conf.getConnectors()) {
for (Role role : conn.getRoles()) {
if (role.getDirection() != null && !overwriteArchitecture) {
continue;
}
RoleTypeMapping mapping = styleMapping.getRoleTypeMapping(role.getStyleType());
if (mapping != null && mapping.getDirection() != null) {
role.setDirection(Role.RoleDirection.valueOf(mapping.getDirection().name()));
} else {
role.setDirection(Role.RoleDirection.unknown);
}
}
}
}
public static Configuration getArchitectureFromExtensionPoint(IFile adlFile) {
IAdlConverter converter = null;
for (IConfigurationElement conf : getConfigurationElementsOfAdlTypeExtensionPoint()) {
String fileExt = conf.getAttribute("fileExtension");
String adlFilename = adlFile.getName();
if (adlFilename == null) {
adlFilename = "";
}
if (adlFilename.endsWith(fileExt)) {
try {
converter = (IAdlConverter) conf.createExecutableExtension("converterClass");
} catch (CoreException e) {
throw new ArchMapperException("Could not convert ADL file "+
adlFile.getName(), e);
}
}
}
if (converter == null) {
throw new ArchMapperException("No converter for the project's architecture file could be found!");
}
Configuration conf = converter.convertFromAdl(adlFile);
conf.setAdlFile(adlFile);
return conf;
}
private static List<IConfigurationElement> getConfigurationElementsOfAdlTypeExtensionPoint() {
IExtension[] extensions = Platform.getExtensionRegistry()
.getExtensionPoint("archmapper.main.AdlTypeRegistration")
.getExtensions();
List<IConfigurationElement> confElems = new ArrayList<IConfigurationElement>();
for (IExtension extension : extensions) {
for (IConfigurationElement conf : extension.getConfigurationElements()) {
confElems.add(conf);
}
}
return confElems;
}
/**
* Reads the extension point AdlTypeRegistration and return information about all registered
* formats.
*
* @return
*/
public static List<AdlType> getAvailableADLTypes() {
List<AdlType> types = new ArrayList<AdlType>();
for (IConfigurationElement conf : getConfigurationElementsOfAdlTypeExtensionPoint()) {
AdlType type = new AdlType();
type.name = conf.getAttribute("adlName");
type.filenameEnding = conf.getAttribute("fileExtension");
types.add(type);
}
return types;
}
private static StyleMapping getStyleMappingFromExtensionPoint(String mappingName, String styleName) {
for (IConfigurationElement conf : getAllStyleMappingExtensions()) {
String thisMappingName = conf.getAttribute("mappingName");
String thisStyleName = conf.getAttribute("styleName");
if ((mappingName != null && mappingName.equals(thisMappingName)) ||
(styleName != null && styleName.equals(thisStyleName))) {
try {
Bundle bundle = Platform.getBundle(
((IExtension) conf.getParent()).getContributor().getName());
URL url = bundle.getResource(conf.getAttribute("xmlFile"));
StyleMapping mapping = StyleMappingDAO.read((InputStream) url.getContent());
return mapping;
} catch (Exception e) {
throw new ArchMapperException("Error trying to get a style mapping from an extension point: " + e.getMessage(), e);
}
}
}
return null;
}
/**
* Returns the names of all architectural styles for which style mappings
* are available.
*
* @return a list of names, never null. Every style name is included only once.
*/
public static List<String> getAllAvailableStylesFromExtensionPoint() {
List<String> styles = new ArrayList<String>();
for (IConfigurationElement elem : getAllStyleMappingExtensions()) {
String style = elem.getAttribute("styleName");
if (!styles.contains(style)) {
styles.add(style);
}
}
return styles;
}
/**
* Returns all configuration elements from the extension point
* "archmapper.main.StyleMappingRegistration"
*
* @return a list of configuration elements, never null
*/
private static List<IConfigurationElement> getAllStyleMappingExtensions() {
IExtension[] extensions = Platform.getExtensionRegistry()
.getExtensionPoint("archmapper.main.StyleMappingRegistration")
.getExtensions();
List<IConfigurationElement> elems = new ArrayList<IConfigurationElement>();
for (IExtension extension : extensions) {
for (IConfigurationElement conf : extension.getConfigurationElements()) {
elems.add(conf);
}
}
return elems;
}
/**
* @return the archMapping
*/
public ArchitectureMapping getArchMapping() {
return archMapping;
}
/**
* @return the conf
*/
public Configuration getArchitecture() {
return conf;
}
/**
* @return the project
*/
public IProject getProject() {
return project;
}
/**
* @return the styleMapping
*/
public StyleMapping getStyleMapping() {
return styleMapping;
}
}