package easysm.stores;
import java.util.List;
import easysm.datatypes.Name;
import easysm.datatypes.information.*;
import easysm.datatypes.visualization.ClassDiagramVis;
import easysm.factories.ListFactory;
/**
* @author FourCheeses Software Solutions
*/
public class ClassDiagram extends Element
{
/**
* Required field to make serialization more robust. See documentation for
* technical details.
*/
private static final long serialVersionUID = -8357799694825425053L;
private Class context;
private List<Class> classes = ListFactory.createList(Class.class);
private List<Enumeration> enums = ListFactory.createList(Enumeration.class);
private List<Type> types = ListFactory.createList(Type.class);
private ClassDiagramVis vis;
public ClassDiagram(ClassDiagramInfo cdInfo)
{
super(cdInfo);
vis = new ClassDiagramVis(this);
// Predefined types
types.add(Type.BOOLEAN);
types.add(Type.INTEGER);
types.add(Type.REAL);
types.add(Type.STRING);
}
/*
*
* Properties
*
*/
/**
* @return The context class, or null if context class is not (yet) defined.
*/
public Class context()
{
return context;
}
public void changeContext(Class newContext)
{
context = newContext;
}
public List<Class> classes()
{
return classes;
}
public List<Enumeration> enums()
{
return enums;
}
/**
* Returns all the available types, i.e., the predefined ones and those
* introduced by the class diagram.
*/
public List<Type> types()
{
return types;
}
public ClassDiagramVis vis()
{
return vis;
}
/*
*
* Operations called by Main
*
*/
public void addCDElement(Class cl)
{
if (classes.add(cl)) {
types.add(Type.classAsType(cl));
}
}
public void deleteCDElement(Class cl)
{
if (classes.remove(cl)) {
types.remove(getTypeByName(cl.name()));
}
}
public void updateCDElement(Class cl,
ClassInfo newClInfo)
{
Name newClName = newClInfo.name();
Type type = getTypeByName(cl.name());
cl.changeName(newClName);
type.refreshFromClass(cl);
}
public void addCDElement(Enumeration en)
{
enums.add(en);
types.add(Type.enumAsType(en));
}
public void deleteCDElement(Enumeration en)
{
enums.remove(en);
types.remove(getTypeByName(en.name()));
}
public void updateCDElement(Enumeration en,
EnumerationInfo newEnInfo)
{
Name newEnName = newEnInfo.name();
Type type = getTypeByName(en.name());
en.changeName(newEnName);
en.changeLiterals(newEnInfo.literalsInfo());
type.refreshFromEnum(en);
}
public void addCDElement(Attribute attr)
{
((Class) attr.containedIn()).attributes().add(attr);
}
public void deleteCDElement(Attribute attr)
{
((Class) attr.containedIn()).attributes().remove(attr);
}
public void updateCDElement(Attribute attr,
AttributeInfo newAttrInfo)
{
attr.changeName(newAttrInfo.name());
attr.changeType(newAttrInfo.type());
}
public void addCDElement(Operation op)
{
((Class) op.containedIn()).operations().add(op);
}
public void deleteCDElement(Operation op)
{
((Class) op.containedIn()).operations().remove(op);
}
public void updateCDElement(Operation op,
OperationInfo newOpInfo)
{
op.changeName(newOpInfo.name());
op.changeParameters(newOpInfo.parametersInfo());
op.changeReturnType(newOpInfo.returnType());
}
/*
*
* Public methods
*
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
if (context != null) {
builder.append("context " + classToString(context));
}
for (Class cl : classes()) {
if (cl != context) {
builder.append(classToString(cl));
}
}
for (Enumeration en : enums()) {
builder.append(enumToString(en));
}
return builder.toString();
}
/*
*
* Private methods
*
*/
private Type getTypeByName(Name typeName)
{
Type type = null;
for (Type t : types) {
if (t.name().equals(typeName)) {
type = t;
break;
}
}
return type;
}
private String classToString(Class cl)
{
StringBuilder builder = new StringBuilder();
String fsp = " "; // 4 spaces, tabs seem too large
boolean empty = true; // Used to understand if a class is empty
// Class begin
builder.append("class " + cl.name() + " {\n");
// Attributes
if (!cl.attributes().isEmpty()) {
empty = false;
builder.append(fsp + "// Attributes\n");
for (Attribute attr : cl.attributes()) {
builder.append(fsp + attr + ";\n");
}
}
// Operations
if (!cl.operations().isEmpty()) {
empty = false;
builder.append(fsp + "// Operations\n");
for (Operation op : cl.operations()) {
builder.append(fsp + op + ";\n");
}
}
// Class end
if (empty) {
builder.append(fsp + "// Empty\n");
}
builder.append("}\n\n");
return builder.toString();
}
private String enumToString(Enumeration en)
{
StringBuilder builder = new StringBuilder();
String fsp = " "; // 4 spaces, tabs seem too large
boolean empty = true; // Used to understand if an enumeration is empty
// Enumeration begin
builder.append("enum " + en.name() + " {\n");
// Literals
if (!en.literals().isEmpty()) {
empty = false;
boolean first = true;
for (Literal lit : en.literals()) {
if (first) {
builder.append(fsp + lit);
first = false;
} else {
builder.append(",\n" + fsp + lit);
}
}
builder.append('\n');
}
// Enumeration end
if (empty) {
builder.append(fsp + "// Empty\n");
}
builder.append("}\n\n");
return builder.toString();
}
}