mim.integration initial commit.

This commit is contained in:
bitwave 2013-05-25 16:31:35 +02:00
parent 8fa4d79ad7
commit edb21f1319
11 changed files with 2780 additions and 0 deletions

2
ch.bitwave.mim.integration/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/target
/.settings

View File

@ -0,0 +1,29 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ch.bitwave</groupId>
<artifactId>maven.platform.parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>mim.integration</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>ch.bitwave</groupId>
<artifactId>platform</artifactId>
</dependency>
<dependency>
<groupId>ch.bitwave</groupId>
<artifactId>mim.meta</artifactId>
</dependency>
<dependency>
<groupId>ch.bitwave</groupId>
<artifactId>parser.delphi</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,383 @@
package ch.bitwave.mim.integration.delphi;
import java.util.Stack;
import javax.annotation.Nonnull;
import org.apache.commons.lang.StringUtils;
import ch.bitwave.lang.delphi.ast.AncestorDeclaration;
import ch.bitwave.lang.delphi.ast.ArrayType;
import ch.bitwave.lang.delphi.ast.ClassType;
import ch.bitwave.lang.delphi.ast.ClassifierDeclaration;
import ch.bitwave.lang.delphi.ast.DelphiSyntaxAdapter;
import ch.bitwave.lang.delphi.ast.FieldDeclaration;
import ch.bitwave.lang.delphi.ast.Identifier;
import ch.bitwave.lang.delphi.ast.InterfaceSection;
import ch.bitwave.lang.delphi.ast.InterfaceType;
import ch.bitwave.lang.delphi.ast.MemberConstructorDeclaration;
import ch.bitwave.lang.delphi.ast.MemberConstructorImplementation;
import ch.bitwave.lang.delphi.ast.MemberDestructorDeclaration;
import ch.bitwave.lang.delphi.ast.MemberDestructorImplementation;
import ch.bitwave.lang.delphi.ast.MemberFunctionDeclaration;
import ch.bitwave.lang.delphi.ast.MemberFunctionImplementation;
import ch.bitwave.lang.delphi.ast.MemberProcedureDeclaration;
import ch.bitwave.lang.delphi.ast.MemberProcedureImplementation;
import ch.bitwave.lang.delphi.ast.MethodDeclaration;
import ch.bitwave.lang.delphi.ast.Node;
import ch.bitwave.lang.delphi.ast.QualifiedIdentifier;
import ch.bitwave.lang.delphi.ast.Type;
import ch.bitwave.lang.delphi.ast.TypeDeclaration;
import ch.bitwave.lang.delphi.ast.Unit;
import ch.bitwave.lang.delphi.ast.UsesSection;
import ch.bitwave.lang.delphi.ast.VariableDeclaration;
import ch.bitwave.lang.delphi.mapping.DelphiSyntaxWriter;
import ch.bitwave.mim.m2.core.Classifier;
import ch.bitwave.mim.m2.core.Dependent;
import ch.bitwave.mim.m2.core.Generalization;
import ch.bitwave.mim.m2.core.MimClass;
import ch.bitwave.mim.m2.core.MimElement;
import ch.bitwave.mim.m2.core.MimPackage;
import ch.bitwave.mim.m2.core.MimType;
import ch.bitwave.mim.m2.core.NamedElement;
import ch.bitwave.mim.m2.core.Operation;
import ch.bitwave.mim.m2.core.Property;
import ch.bitwave.mim.m2.core.StubClass;
import ch.bitwave.mim.m2.core.StubType;
import ch.bitwave.mim.m2.core.UnknownMemberException;
import ch.bitwave.mim.m2.profiles.DelphiProfile;
/**
* Maps a Delphi AST into a Mim M2 model.
*/
public class DelphiASTMapper extends DelphiSyntaxAdapter {
// private static final Logger LOGGER =
// Logger.getLogger(DelphiMappingVisitor.class
// .getSimpleName());
private Stack<MimElement> stack;
DelphiProfile profile;
public DelphiASTMapper(final DelphiProfile profile, final MimPackage parent) {
this.stack = new Stack<MimElement>();
this.profile = profile;
this.stack.push(parent);
}
private void pop(final MimElement element) {
this.stack.pop();
}
private void push(final MimElement element) {
this.stack.push(element);
}
@Override
public void visitUnit(final Unit node) {
MimPackage parent = getParentAs(MimPackage.class);
MimPackage unitPackage = this.profile.createPackage(node.getIdentifier().getName());
parent.addOwnedMember(unitPackage);
push(unitPackage);
super.visitUnit(node);
pop(unitPackage);
}
@Override
public void visitClassType(final ClassType node) {
processClassifier(node);
}
@Override
public void visitInterfaceType(final InterfaceType node) {
MimClass type = processClassifier(node);
if (type != null) {
type.addStereotype(this.profile.getInterfaceStereotype());
}
}
private MimClass processClassifier(final ClassifierDeclaration node) {
if (!(node.getParent() instanceof TypeDeclaration)) {
throw new RuntimeException(String.format(
"%s is not subordinate to a type declaration.", node));
}
TypeDeclaration dec = (TypeDeclaration) node.getParent();
MimPackage parent = getParentAs(MimPackage.class);
String name = dec.getIdentifier().getName();
MimClass type = parent.findOwnedMemberAs(name, MimClass.class);
if (type == null) {
type = this.profile.createClass(name);
type.setOwner(parent);
}
type.setAbstract(node.isAbstract());
parent.addOwnedMember(type);
push(type);
descend(node);
pop(type);
return type;
}
@Override
public void visitMemberConstructorDeclaration(final MemberConstructorDeclaration node) {
declareMethod(node);
super.visitMemberConstructorDeclaration(node);
}
@Override
public void visitMemberDestructorDeclaration(final MemberDestructorDeclaration node) {
declareMethod(node);
super.visitMemberDestructorDeclaration(node);
}
@Override
public void visitMemberFunctionDeclaration(final MemberFunctionDeclaration node) {
declareMethod(node);
super.visitMemberFunctionDeclaration(node);
}
@Override
public void visitMemberProcedureDeclaration(final MemberProcedureDeclaration node) {
declareMethod(node);
super.visitMemberProcedureDeclaration(node);
}
@Override
public void visitMemberConstructorImplementation(final MemberConstructorImplementation node) {
MimPackage pack = getFirstParentAs(MimPackage.class);
try {
QualifiedIdentifier methodIdent = node.getIdentifier();
MimClass parent = (MimClass) pack.getOwnedMemberByName(methodIdent.getNamespaceName());
Operation method = (Operation) parent.getOwnedMemberByName(methodIdent.getObjectName());
push(method);
super.visitMemberConstructorImplementation(node);
pop(method);
} catch (UnknownMemberException e) {
throw new RuntimeException(String.format(
"Failed to map method implementation %s due to: %s", node, e.getMessage()), e);
}
}
@Override
public void visitMemberDestructorImplementation(final MemberDestructorImplementation node) {
MimPackage pack = getFirstParentAs(MimPackage.class);
try {
QualifiedIdentifier methodIdent = node.getIdentifier();
MimClass parent = (MimClass) pack.getOwnedMemberByName(methodIdent.getNamespaceName());
Operation method = (Operation) parent.getOwnedMemberByName(methodIdent.getObjectName());
push(method);
super.visitMemberDestructorImplementation(node);
pop(method);
} catch (UnknownMemberException e) {
throw new RuntimeException(String.format(
"Failed to map method implementation %s due to: %s", node, e.getMessage()), e);
}
}
@Override
public void visitMemberFunctionImplementation(final MemberFunctionImplementation node) {
MimPackage pack = getFirstParentAs(MimPackage.class);
try {
QualifiedIdentifier methodIdent = node.getIdentifier();
MimClass parent = (MimClass) pack.getOwnedMemberByName(methodIdent.getNamespaceName());
Operation method = (Operation) parent.getOwnedMemberByName(methodIdent.getObjectName());
push(method);
super.visitMemberFunctionImplementation(node);
pop(method);
} catch (UnknownMemberException e) {
throw new RuntimeException(String.format(
"Failed to map method implementation %s due to: %s", node, e.getMessage()), e);
}
}
@Override
public void visitMemberProcedureImplementation(final MemberProcedureImplementation node) {
MimPackage pack = getFirstParentAs(MimPackage.class);
try {
QualifiedIdentifier methodIdent = node.getIdentifier();
MimClass parent = (MimClass) pack.getOwnedMemberByName(methodIdent.getNamespaceName());
Operation method = (Operation) parent.getOwnedMemberByName(methodIdent.getObjectName());
push(method);
super.visitMemberProcedureImplementation(node);
pop(method);
} catch (UnknownMemberException e) {
throw new RuntimeException(String.format(
"Failed to map method implementation %s due to: %s", node, e.getMessage()), e);
}
}
@Override
public void visitAncestorDeclaration(final AncestorDeclaration node) {
MimClass parent = getParentAs(MimClass.class);
for (Identifier ancestorId : node.getAncestors()) {
Classifier general = resolveClassReference(parent.getPackage(), ancestorId);
Generalization gen = new Generalization();
if (general instanceof StubClass) {
((StubClass) general).addReferer(gen);
}
gen.setGeneral(general);
gen.setSpecific(parent);
}
}
@Override
public void visitFieldDeclaration(final FieldDeclaration node) {
MimClass parent = getParentAs(MimClass.class);
VariableDeclaration var = node.getVariable();
Type type = var.getType();
for (Identifier ident : var.getIdentifiers()) {
Property field = new Property();
field.setName(ident.getName());
field.setDefaultValue(representNode(var.getDefaultValue()));
int upperBound = 1;
if (type instanceof ArrayType) {
type = ((ArrayType) type).getComponentType();
upperBound = 0;
}
String typeName = representNode(type);
MimType modelType = resolveType(typeName);
field.setType(modelType);
field.getMultiplicity().setUpper(upperBound);
parent.addOwnedMember(field);
}
}
/**
* Attempts to resolve the type for the given type name. The profile is
* searched first, followed by the package members. If the type is unknown,
* a type stub is created and registered with the package.
*
* @param typeName
* the name of the type to resolve.
* @return the resolved type.
*/
@Nonnull
private MimType resolveType(final String typeName) {
MimType result = this.profile.findType(typeName);
if (result == null) {
MimPackage parent = getFirstParentAs(MimPackage.class);
result = parent.findType(typeName);
if (result == null) {
createStubType(parent, typeName, String.format(
"Type %s is neither provided by the profile nor known to package %s.",
typeName, parent.getName()));
}
}
return result;
}
@Override
public void visitInterfaceSection(final InterfaceSection node) {
UsesSection usesSection = node.getUsesSection();
if (usesSection != null) {
MimPackage parent = getParentAs(MimPackage.class);
for (Identifier importedIdentifier : usesSection.getImports()) {
parent.addPackageImportStub(importedIdentifier.getName());
}
}
super.visitInterfaceSection(node);
}
@Override
public void visitIdentifier(final Identifier node) {
Dependent parent = findFirstParentAs(Dependent.class);
if (parent != null) {
parent.addIdentifierDependency(node.getName());
}
}
private String representNode(final Node node) {
if (node == null) {
return StringUtils.EMPTY;
}
return DelphiSyntaxWriter.writeToString(node);
}
/**
* Resolves the class with the given identifier within the given parent
* package. Creates a stub class in case the class is not known.
*
* @param parent
* @param identifier
* @return
*/
private Classifier resolveClassReference(final MimPackage parent, final Identifier identifier) {
String name = identifier.getName();
try {
NamedElement general = parent.getMemberByName(name);
if (!(general instanceof Classifier)) {
String message = String.format("Class %s generalizes non-classifier \"%s\".",
general.getName(), name);
// LOGGER.warning(message);
general = createStubClass(parent, identifier, message);
}
return (Classifier) general;
} catch (UnknownMemberException e) {
String message = String.format(
"Class %s generalizes \"%s\", which is not known to package \"%s\".",
parent.getName(), name, parent.getName());
// LOGGER.warning(message);
return createStubClass(parent, identifier, message);
}
}
private Classifier createStubClass(final MimPackage parent, final Identifier identifier,
final String message) {
StubClass stub = new StubClass();
stub.setName(identifier.getName());
stub.setStubReason(message);
parent.addOwnedMember(stub);
return stub;
}
private MimType createStubType(final MimPackage parent, final String typeName,
final String format) {
StubType stub = new StubType();
stub.setName(typeName);
parent.addOwnedMember(stub);
return stub;
}
private void declareMethod(final MethodDeclaration node) {
Classifier parent = getParentAs(Classifier.class);
Operation op = new Operation();
op.setName(node.getIdentifier().getName());
parent.addOwnedMember(op);
}
@SuppressWarnings("unchecked")
private <T> T getParentAs(final java.lang.Class<T> elementClass) {
if (this.stack.isEmpty()) {
throw new RuntimeException(
"Cannot return the current parent because the element stack is empty.");
}
return (T) this.stack.get(this.stack.size() - 1);
}
/**
* Ascends the element stack until an element of the given type is found.
*
* @param elementClass
* the type to retrieve from the stack.
* @return
*/
private <T> T getFirstParentAs(final Class<T> elementClass) {
T result = findFirstParentAs(elementClass);
if (result == null) {
throw new RuntimeException(String.format(
"There is no element of type %s present on the stack.",
elementClass.getSimpleName()));
}
return result;
}
@SuppressWarnings("unchecked")
private <T> T findFirstParentAs(final Class<T> elementClass) {
for (int i = this.stack.size() - 1; i >= 0; i--) {
MimElement cur = this.stack.get(i);
if (elementClass.isAssignableFrom(cur.getClass())) {
return (T) cur;
}
}
return null;
}
}

View File

@ -0,0 +1,161 @@
package ch.bitwave.mim.integration.delphi;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import javax.annotation.Nonnull;
import org.apache.commons.io.FileUtils;
import ch.bitwave.lang.delphi.ast.Unit;
import ch.bitwave.lang.delphi.driver.DelphiSourceParserDriver;
import ch.bitwave.mim.integration.toolbox.FileSystem;
import ch.bitwave.mim.m2.core.Classifier;
import ch.bitwave.mim.m2.core.MimClass;
import ch.bitwave.mim.m2.core.MimPackage;
import ch.bitwave.mim.m2.core.PackageImport;
import ch.bitwave.mim.m2.core.StubClass;
import ch.bitwave.mim.m2.core.StubPackage;
import ch.bitwave.mim.m2.profiles.DelphiProfile;
/**
* Integrates a Delphi AST into the mim workspace by transforming it into m2
* elements.
*/
public class DelphiIntegrator {
private static final Logger LOGGER = Logger.getLogger(DelphiIntegrator.class.getSimpleName());
private File rootFolder;
public File getRootFolder() {
return this.rootFolder;
}
public void setRootFolder(final File rootFolder) {
this.rootFolder = rootFolder;
}
public DelphiIntegrator(final File rootFolder) {
this.rootFolder = rootFolder;
}
/**
* Integrates the given unit below the given target namespace. The package
* hierarchy is derived from the fully qualified path name stored in the
* unit as expressed relative to the absolute root folder specified for the
* integrator.
*
* @param targetPackage
* @param unit
*/
public void integrate(final DelphiProfile profile, final MimPackage targetPackage,
final Unit unit) {
MimPackage parent = ensurePackageHierarchy(targetPackage, unit.getSourceLocation());
DelphiASTMapper visitor = new DelphiASTMapper(profile, parent);
unit.accept(visitor);
}
public void integrateFolder(final DelphiProfile profile, final MimPackage targetPackage,
final File folder, final boolean recursive, final String encoding) throws IOException {
LOGGER.info(String.format("Integrating folder %s.", folder.getAbsolutePath()));
Collection<File> found = FileUtils.listFiles(folder, new String[] { "pas" }, recursive);
for (File file : found) {
integrateFile(profile, targetPackage, file, encoding);
}
}
public void integrateFile(final DelphiProfile profile, final MimPackage targetPackage,
final File file, final String encoding) throws IOException {
LOGGER.info(String.format("Integrating file %s.", file.getAbsolutePath()));
Unit unit = new DelphiSourceParserDriver().readFile(file, encoding);
unit.setSourceLocation(file);
integrate(profile, targetPackage, unit);
}
/**
* Attempts to replace all Stub classes with the actual classes they
* represent.
*/
public void resolveStubs(final MimPackage rootPackage) {
resolvePackageStubs(rootPackage, rootPackage);
resolveClassStubs(rootPackage);
}
private void resolvePackageStubs(final MimPackage rootPackage, final MimPackage subject) {
List<PackageImport> imports = subject.getPackageImports();
Map<String, MimPackage> nonStubs = rootPackage.getAllOwnedNonStubPackages(true);
for (PackageImport pimp : imports) {
MimPackage target = pimp.getImportedPackage();
if (target.isStub()) {
StubPackage stub = (StubPackage) target;
MimPackage resolved = nonStubs.get(stub.getName().toLowerCase());
if (resolved != null) {
stub.replaceWith(resolved);
LOGGER.info(String.format("Replaced %s with %s.", stub, resolved));
}
}
}
for (MimPackage subPackage : subject.getNestedPackages()) {
resolvePackageStubs(rootPackage, subPackage);
}
}
private void resolveClassStubs(final MimPackage rootPackage) {
List<StubClass> stubs = rootPackage.getOwnedMembersOfType(StubClass.class);
Map<String, MimClass> nonStubs = rootPackage.getAllNonStubClasses(true);
for (StubClass stub : stubs) {
Classifier resolved = nonStubs.get(stub.getName().toLowerCase());
if (resolved instanceof MimClass) {
stub.replaceWith((MimClass) resolved);
}
}
for (MimPackage subPackage : rootPackage.getNestedPackages()) {
resolveClassStubs(subPackage);
}
}
/**
* <p>
* Returns the effective package in which to place the types introduced in
* the given unit, based on the given source location of the unit in
* relation to the integrator's root folder. Existing packages are reused.
* </p>
*
* Example: If the integrator root is "C:/source/" and the unit location is
* "C:/source/magic/mushroom/dust.pas" then the resulting package will be
* root.magic.mushroom.
*
* @param rootPackage
* the package below which to add detail packages.
* @param sourceLocation
* the location of the unit, including the unit file name.
* @return
*/
protected MimPackage ensurePackageHierarchy(@Nonnull final MimPackage rootPackage,
@Nonnull final File sourceLocation) {
File sourceFolder = sourceLocation.getParentFile();
String[] packageNames = FileSystem.getRelativeFolders(this.rootFolder, sourceFolder);
if (packageNames.length == 0) {
return rootPackage;
}
MimPackage result = rootPackage;
for (String packageName : packageNames) {
result = ensureDetailPackage(result, packageName);
}
return result;
}
private MimPackage ensureDetailPackage(final MimPackage parent, final String packageName) {
MimPackage detailMember = parent.findOwnedMemberAs(packageName, MimPackage.class);
if (detailMember == null) {
detailMember = new MimPackage();
detailMember.setName(packageName);
parent.addOwnedMember(detailMember);
}
return detailMember;
}
}

View File

@ -0,0 +1,24 @@
package ch.bitwave.mim.integration.toolbox;
import java.io.File;
public class FileSystem {
public static String[] getRelativeFolders(final File root, final File detail) {
String rootPath = root.getAbsolutePath();
String detailPath = detail.getAbsolutePath();
if (detailPath.length() < rootPath.length()
|| !detailPath.toLowerCase().startsWith(rootPath.toLowerCase())) {
throw new RuntimeException(String.format("Path \"%s\" does not root in \"%s\".",
detailPath, rootPath));
}
String relativePath = detailPath.substring(rootPath.length());
if (relativePath.startsWith(File.separator)) {
relativePath = relativePath.substring(1);
}
if (relativePath.isEmpty()) {
return new String[0];
}
return relativePath.split("[\\\\/]");
}
}

View File

@ -0,0 +1,102 @@
package ch.bitwave.mim.integration.delphi;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import org.junit.Test;
import ch.bitwave.lang.delphi.ast.Unit;
import ch.bitwave.lang.delphi.driver.DelphiSourceParserDriver;
import ch.bitwave.mim.integration.testbase.Resources;
import ch.bitwave.mim.m2.core.Classifier;
import ch.bitwave.mim.m2.core.MimClass;
import ch.bitwave.mim.m2.core.MimPackage;
import ch.bitwave.mim.m2.core.Operation;
import ch.bitwave.mim.m2.core.UnknownMemberException;
import ch.bitwave.mim.m2.profiles.DelphiProfile;
/**
* Tests the integration of Delphi sources into the metamodel.
*/
public class DelphiIntegratorTest {
@Test
public void shouldMapPhoenixInterfaces() throws IOException, UnknownMemberException {
DelphiIntegrator integrator = createIntegrator();
DelphiProfile profile = new DelphiProfile();
MimPackage rootPackage = new MimPackage();
rootPackage.setName("root");
integrateUnit(integrator, "product/common/", "SampleUnit7.pas", profile, rootPackage);
MimPackage phoenixPackage = (MimPackage) rootPackage.getOwnedMemberByName("product");
MimPackage sharedPackage = (MimPackage) phoenixPackage.getOwnedMemberByName("common");
MimPackage pxiPackage = (MimPackage) sharedPackage.getOwnedMemberByName("SampleUnit7");
assertEquals(5, pxiPackage.getOwnedMembersOfType(MimClass.class).size());
MimClass clientLanguage = (MimClass) pxiPackage.getOwnedMemberByName("IClientLanguage");
assertEquals("IClientLanguage", clientLanguage.getName());
assertEquals(pxiPackage, clientLanguage.getNamespace());
MimClass person = (MimClass) pxiPackage.getMemberByName("IPerson");
assertEquals(1, person.getGenerals().size());
Classifier general = person.getGenerals().get(0);
assertEquals("IHuman", general.getName());
assertTrue(general.isStereotype(profile.getInterfaceStereotype()));
}
@Test
public void shouldResolveStubClasses() throws IOException, UnknownMemberException {
DelphiIntegrator integrator = createIntegrator();
DelphiProfile profile = new DelphiProfile();
MimPackage rootPackage = new MimPackage();
rootPackage.setName("root");
integrateUnit(integrator, "product/common/", "SampleUnit7.pas", profile, rootPackage);
integrateUnit(integrator, "independent/toolbox/", "SampleUnit3.pas", profile, rootPackage);
integrator.resolveStubs(rootPackage);
MimPackage tbi = rootPackage.findContainedPackage("SampleUnit3");
MimClass stordef = (MimClass) tbi.getOwnedMemberByName("IStorableDefinition");
MimPackage pxi = rootPackage.findContainedPackage("SampleUnit7");
MimClass dawg = (MimClass) pxi.getOwnedMemberByName("IDogDefinition");
assertTrue(dawg.isSpecializationOf(stordef));
}
@Test
public void shouldMapImplementationIdentifierDependencies() throws IOException,
UnknownMemberException {
DelphiIntegrator integrator = createIntegrator();
DelphiProfile profile = new DelphiProfile();
MimPackage rootPackage = new MimPackage();
rootPackage.setName("root");
integrateUnit(integrator, "varia", "Planets.pas", profile, rootPackage);
MimPackage planets = rootPackage.findContainedPackage("Varia").findContainedPackage(
"Planets");
MimClass mercury = (MimClass) planets.getOwnedMemberByName("TMercury");
assertFalse(mercury.depdendsOnIdentifier("cstrGUID_Venus"));
Operation method = (Operation) mercury.getOwnedMemberByName("DoThing");
assertTrue(method.depdendsOnIdentifier("cstrGUID_Venus"));
}
private DelphiIntegrator createIntegrator() {
// Let's fake a relative location of the unit in subfolders
// phoenix/shared to force creating of the respective package tree.
String rootPath = "D:/delphi-source/";
File rootFolder = new File(rootPath);
DelphiIntegrator integrator = new DelphiIntegrator(rootFolder);
return integrator;
}
private void integrateUnit(final DelphiIntegrator integrator, final String relativePath,
final String fileName, final DelphiProfile profile, final MimPackage rootPackage)
throws IOException {
File file = new File(Resources.RESOURCE_FOLDER + fileName);
File unitLocation = new File(new File(integrator.getRootFolder(), relativePath), fileName);
Unit unit = new DelphiSourceParserDriver().readFile(file, Resources.ENCODING);
// System.out.print(DelphiASTPrinter.writeToString(unit));
unit.setSourceLocation(unitLocation);
integrator.integrate(profile, rootPackage, unit);
}
}

View File

@ -0,0 +1,6 @@
package ch.bitwave.mim.integration.testbase;
public class Resources {
public static final String RESOURCE_FOLDER = "src/test/resources/ch/bitwave/mim/integration/delphi/";
public static final String ENCODING = "ISO-8859-1";
}

View File

@ -0,0 +1,36 @@
package ch.bitwave.mim.integration.toolbox;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Arrays;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
public class FileSystemTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Test
public void shouldGetRelativeFolders() {
String[] folders = FileSystem.getRelativeFolders(new File("c:/root"), new File(
"c:/root/alpha/beta"));
assertTrue(Arrays.deepEquals(new String[] { "alpha", "beta" }, folders));
}
@Test
public void shouldGetEmptyListForIdenticalPaths() {
String[] folders = FileSystem.getRelativeFolders(new File("c:/root"), new File("c:/ROOT"));
assertTrue(folders.length == 0);
}
@Test
public void shouldExceptOnGetRelativeFoldersWithIncompatiblePaths() {
this.thrown.expect(RuntimeException.class);
this.thrown.expectMessage("Path \"c:\\root\\alpha\\beta\" does not root in \"c:\\bar\".");
FileSystem.getRelativeFolders(new File("c:/bar"), new File("c:/root/alpha/beta"));
}
}

View File

@ -0,0 +1,51 @@
unit Planets;
interface
type
TMercury = class
public
procedure DoThing;
end;
TVenus = class
public
procedure DoThing;
end;
TEarth = class
public
procedure DoThing;
end;
TMars = class
public
procedure DoThing;
end;
implementation
procedure TMercury.DoThing;
begin
SomeFunction(cstrGUID_Venus);
end;
procedure TVenus.DoThing;
begin
SomeFunction(cstrGUID_Earth);
SomeFunction(cstrGUID_Mars);
end;
procedure TEarth.DoThing;
begin
SomeFunction(cstrGUID_Mars);
end;
procedure TMars.DoThing;
begin
SomeFunction(cstrGUID_Jupiter);
end;
end.

View File

@ -0,0 +1,83 @@
{*
*}
unit SampleUnit7;
interface
uses
Classes,
Graphics,
Windows,
Forms,
SampleUnit3,
SysUtils;
const
cstrGUID_IHuman = '{82F52648-B94D-495C-B0A6-8BD4BF904846}';
cstrGUID_IClientLanguage = '{6EA63F22-6809-4E85-960C-154421491506}';
cstrGUID_IPerson = '{06B54C9E-6C85-4075-BDED-85406083648D}';
cstrGUID_IDogDefinition = '{364A99BE-C420-4CA1-AA0C-0CA9C0568B59}';
type
IHuman = interface
[cstrGUID_IHuman]
function FormatProperties(const strProperties: string = '<titeltext> <vorname> <name>'; const
blnRespectLanguageOrder: boolean = false): string;
function GetAnrede: integer;
function GetAnredeText: string;
function GetExists: boolean;
function GetName: string;
function GetPropertyCount: integer;
function GetPropertyValue(const strName: string): string;
function GetTitel: integer;
function GetTitelText: string;
function GetVorname: string;
function GetUID: integer;
function GetAsText: string;
procedure SetFromText(const strText: string);
procedure SetPropertyValue(const strName, strValue: string);
end;
IPerson = interface(IHuman)
[cstrGUID_IPerson]
function GetGroupID: integer;
function GetKSTelle: string;
function GetPersID: integer;
function GetVisum: string;
function GetID: integer;
procedure SetID(const intID: integer);
procedure SetTitleCode(const intTitleCode: integer);
procedure SetFirstname(const strFirstName: string);
procedure SetLastname(const strLastName: string);
procedure SetGroupID(const intID: integer);
end;
IClientLanguage = interface
[cstrGUID_IClientLanguage]
function GetAvailable: boolean;
function GetIsSystemLanguage(out language: ISystemLanguage): boolean;
function GetCode: string;
function GetLabel: string;
function GetRegionCode: integer;
end;
IDogDefinition = interface(IStorableDefinition)
[cstrGUID_IDogDefinition]
function CreateDogDefinitionField: IDogDefinitionField;
function GetDogDefinitionField(const index: integer): IDogDefinitionField;
function GetDogDefinitionFieldCount: integer;
function GetDogDefinitionFieldIndex(const strName: string): integer;
function GetGroupField: string;
function GetName: string;
procedure AddDogDefinitionField(const aField: IDogDefinitionField);
procedure RemoveDogDefinitionField(const aField: IDogDefinitionField); overload;
procedure RemoveDogDefinitionField(const index: integer); overload;
procedure SetGroupField(const strValue: string);
procedure SetName(const strValue: string);
end;
implementation
end.