package au.com.langdale.xmi;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import au.com.langdale.kena.OntResource;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Table;
public class EAPExtractor extends XMIModel {
private File file;
private Database db;
private IDList packageIDs = new IDList(100);
private IDList objectIDs = new IDList(2000);
public EAPExtractor(File file) {
this.file = file;
}
public void run() throws IOException {
db = Database.open(file, true);
try {
gatherPackageIDs();
extractPackages();
extractClasses();
extractAssociations();
extractAttributes();
}
finally {
db.close();
}
}
private void gatherPackageIDs() throws IOException {
OntResource top = createGlobalPackage();
Iterator it = getPackageTable().iterator();
while( it.hasNext()) {
Row row = new Row(it.next());
OntResource subject;
if( row.getName().equals("Model"))
subject = top;
else
subject = createIndividual(row.getXUID(), row.getName(), UML.Package);
packageIDs.putID(row.getPackageID(), subject);
}
}
private void extractPackages() throws IOException {
Iterator it = getPackageTable().iterator();
while( it.hasNext()) {
Row row = new Row(it.next());
OntResource subject = packageIDs.getID(row.getPackageID());
if(! subject.equals(UML.global_package)) {
OntResource parent = packageIDs.getID( row.getParentID());
subject.addIsDefinedBy(parent == null? UML.global_package: parent);
annotate(subject, row.getNotes());
}
}
}
private void annotate(OntResource subject, String note) {
if( note == null)
return;
note = note.trim();
if( note.length() == 0)
return;
subject.addComment(note, LANG);
}
private void extractClasses() throws IOException {
Iterator it = getObjectTable().iterator();
while( it.hasNext()) {
Row row = new Row(it.next());
if( row.getObjectType().equals("Class")) {
OntResource subject = createClass(row.getXUID(), row.getName());
objectIDs.putID(row.getObjectID(), subject);
annotate( subject, row.getNote());
OntResource parent = packageIDs.getID( row.getPackageID());
subject.addIsDefinedBy(parent == null? UML.global_package: parent);
if( row.hasStereotype())
subject.addProperty(UML.hasStereotype, createStereotypeByName(row.getStereotype()));
}
// else
// System.out.println("Ignoring object type " + row.getObjectType() + " id " + row.getObjectID());
}
}
private void extractAttributes() throws IOException {
Iterator it = getAttributeTable().iterator();
while( it.hasNext()) {
Row row = new Row(it.next());
OntResource id = objectIDs.getID(row.getObjectID());
if( id != null ) {
OntResource subject = createAttributeProperty(row.getXUID(), row.getName());
subject.addDomain(id);
annotate( subject, row.getNotes());
subject.addIsDefinedBy(id.getIsDefinedBy());
if( row.hasClassifier()) {
OntResource range = objectIDs.getID(row.getClassifier());
if( range != null)
subject.addRange(range);
else
System.out.println("Could not find the range of attribute " + row.getName() + ". Range ID = " + row.getClassifier());
}
if( row.hasDefault())
subject.addProperty(UML.hasInitialValue, row.getDefault());
}
else
System.out.println("Could not find the domain of attribute " + row.getName() + ". Domain ID = " + row.getObjectID());
}
}
private void extractAssociations() throws IOException {
Iterator it = getConnectorTable().iterator();
while( it.hasNext()) {
Row row = new Row(it.next());
String type = row.getConnectorType();
if( type.equals("Generalization") || type.equals("Association")) {
OntResource source = objectIDs.getID(row.getStartObjectID());
OntResource destin = objectIDs.getID(row.getEndObjectID());
if( source != null && destin != null) {
if( type.equals("Generalization")) {
source.addSuperClass(destin);
}
else {
Role rolea = extractProperty(row.getXUID(), source, destin, row.getDestRole(), row.getDestRoleNote(), row.getDestCard(), row.getDestIsAggregate(), true);
Role roleb = extractProperty(row.getXUID(), destin, source, row.getSourceRole(), row.getSourceRoleNote(), row.getSourceCard(), row.getSourceIsAggregate(), false);
rolea.mate(roleb);
roleb.mate(rolea);
}
}
}
}
}
private Role extractProperty(String xuid, OntResource source, OntResource destin, String name, String note, String card, boolean aggregate, boolean sideA) {
Role role = new Role();
role.property = createObjectProperty(xuid, sideA, name);
annotate( role.property, note);
role.property.addIsDefinedBy(source.getIsDefinedBy()); // FIXME: the package of an association is not always that of the source class
role.range = destin;
role.aggregate = aggregate;
if( card.equals("1") || card.endsWith("..1"))
role.upper = 1;
if( card.equals("*") || card.startsWith("0.."))
role.lower = 0;
else
role.lower = 1;
return role;
}
private Table getPackageTable() throws IOException {
return db.getTable("t_package");
}
private Table getObjectTable() throws IOException {
return db.getTable("t_object");
}
private Table getConnectorTable() throws IOException {
return db.getTable("t_connector");
}
private Table getAttributeTable() throws IOException {
return db.getTable("t_attribute");
}
private class Row {
private Map fields;
Row(Object raw) {
fields = (Map) raw;
}
int getObjectID() {
return getInt("Object_ID");
}
int getPackageID() {
return getInt("Package_ID");
}
int getParentID() {
return getInt("Parent_ID");
}
int getStartObjectID() {
return getInt("Start_Object_ID");
}
int getEndObjectID() {
return getInt("End_Object_ID");
}
int getClassifier() {
Object raw = fields.get("Classifier");
return raw != null ? Integer.parseInt(raw.toString()): 0;
}
boolean hasClassifier() {
return getClassifier() != 0;
}
String getXUID() {
String xuid = fields.get("ea_guid").toString();
return "_" + xuid.substring(1, xuid.length()-1);
}
String getName() {
return getString("Name");
}
String getObjectType() {
return getString("Object_Type");
}
String getConnectorType() {
return getString("Connector_Type");
}
String getNote() {
return getString("Note");
}
String getNotes() {
return getString("Notes");
}
String getStereotype() {
return fields.get("Stereotype").toString();
}
boolean hasStereotype() {
return fields.get("Stereotype") != null;
}
boolean hasDefault() {
return fields.get("Default") != null;
}
String getDefault() {
return fields.get("Default").toString();
}
String getDestRole() {
return getString("DestRole");
}
String getDestRoleNote() {
return getString("DestRoleNote");
}
String getDestCard() {
return getString("DestCard");
}
boolean getDestIsAggregate() {
return getInt("DestIsAggregate") == 1;
}
String getSourceRole() {
return getString("SourceRole");
}
String getSourceRoleNote() {
return getString("SourceRoleNote");
}
String getSourceCard() {
return getString("SourceCard");
}
boolean getSourceIsAggregate() {
return getInt("SourceIsAggregate") == 1;
}
int getInt( String name ) {
Object raw = fields.get(name);
return (raw instanceof Integer)? ((Integer)raw).intValue(): 0;
}
String getString( String name ) {
Object raw = fields.get(name);
return raw != null ? raw.toString(): "";
}
}
@SuppressWarnings("serial")
private class IDList extends ArrayList {
public IDList(int size) {
super(size);
}
public void putID(int index, OntResource id) {
while( index >= size()) {
add(null);
}
set(index, id);
}
public OntResource getID(int index) {
if( index >= size() ) {
return null;
}
OntResource res = (OntResource) get(index);
return res;
}
}
}