blob: 2a6eaa825eefe2c139112b6ac7d477e0ee75bb12 [file] [log] [blame]
/*
* Copyright (c) 2014, 2018 CEA and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Christian W. Damus (CEA) - initial API and implementation
* Kenn Hussey - 535301
*
*/
package org.eclipse.uml2.examples.gettingstarted;
import java.io.File;
import java.io.IOException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.AggregationKind;
import org.eclipse.uml2.uml.Association;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Generalization;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.UMLFactory;
import org.eclipse.uml2.uml.resource.UMLResource;
import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;
/**
* A Java program that may be run stand-alone (with the required EMF and UML2
* bundle JARs on the classpath) to create the example model illustrated in the
* <em>Getting Started with UML2</em> article on the Wiki.
*
* @see http://wiki.eclipse.org/MDT/UML2/Getting_Started_with_UML2
*/
public class GettingStartedWithUML2 {
public static boolean DEBUG = true;
private static File outputDir;
/**
* The main program. It expects one argument, which is the local filesystem
* path of a directory in which to create the <tt>ExtendedPO2.uml</tt> file.
*
* @param the
* program arguments, which must consist of a single filesystem
* path
*/
public static void main(String[] args)
throws Exception {
if (!processArgs(args)) {
System.exit(1);
}
banner("Creating root model package and primitive types.");
// Create the root package (a model).
Model epo2Model = createModel("epo2");
// Create primitive types to be used as types of attributes in our
// classes.
PrimitiveType intPrimitiveType = createPrimitiveType(epo2Model, "int");
PrimitiveType stringPrimitiveType = createPrimitiveType(epo2Model,
"String");
PrimitiveType datePrimitiveType = createPrimitiveType(epo2Model, "Date");
PrimitiveType skuPrimitiveType = createPrimitiveType(epo2Model, "SKU");
// Create enumerations to be used as types of attributes in our classes.
Enumeration orderStatusEnumeration = createEnumeration(epo2Model,
"OrderStatus");
createEnumerationLiteral(orderStatusEnumeration, "Pending");
createEnumerationLiteral(orderStatusEnumeration, "BackOrder");
createEnumerationLiteral(orderStatusEnumeration, "Complete");
banner("Creating model classes.");
// Create the classes.
org.eclipse.uml2.uml.Class supplierClass = createClass(epo2Model,
"Supplier", false);
org.eclipse.uml2.uml.Class customerClass = createClass(epo2Model,
"Customer", false);
org.eclipse.uml2.uml.Class purchaseOrderClass = createClass(epo2Model,
"PurchaseOrder", false);
org.eclipse.uml2.uml.Class itemClass = createClass(epo2Model, "Item",
false);
org.eclipse.uml2.uml.Class addressClass = createClass(epo2Model,
"Address", true);
org.eclipse.uml2.uml.Class usAddressClass = createClass(epo2Model,
"USAddress", false);
org.eclipse.uml2.uml.Class globalAddressClass = createClass(epo2Model,
"GlobalAddress", false);
org.eclipse.uml2.uml.Class globalLocationClass = createClass(epo2Model,
"GlobalLocation", false);
// Create generalization relationships amongst our classes.
createGeneralization(usAddressClass, addressClass);
createGeneralization(globalAddressClass, addressClass);
createGeneralization(globalAddressClass, globalLocationClass);
banner("Creating attributes of model classes.");
// Create attributes in our classes.
createAttribute(supplierClass, "name", stringPrimitiveType, 0, 1);
createAttribute(customerClass, "customerID", intPrimitiveType, 1, 1);
createAttribute(purchaseOrderClass, "comment", stringPrimitiveType, 0,
1);
createAttribute(purchaseOrderClass, "orderDate", datePrimitiveType, 1,
1);
createAttribute(purchaseOrderClass, "status", orderStatusEnumeration,
1, 1);
createAttribute(purchaseOrderClass, "totalAmount", intPrimitiveType, 0,
1);
createAttribute(itemClass, "productName", stringPrimitiveType, 0, 1);
createAttribute(itemClass, "quantity", intPrimitiveType, 0, 1);
createAttribute(itemClass, "usPrice", intPrimitiveType, 0, 1);
createAttribute(itemClass, "comment", stringPrimitiveType, 0, 1);
createAttribute(itemClass, "shipDate", datePrimitiveType, 0, 1);
createAttribute(itemClass, "partNum", skuPrimitiveType, 1, 1);
createAttribute(addressClass, "name", stringPrimitiveType, 0, 1);
createAttribute(addressClass, "country", stringPrimitiveType, 0, 1);
createAttribute(usAddressClass, "street", stringPrimitiveType, 1, 1);
createAttribute(usAddressClass, "city", stringPrimitiveType, 1, 1);
createAttribute(usAddressClass, "state", stringPrimitiveType, 1, 1);
createAttribute(usAddressClass, "zip", stringPrimitiveType, 1, 1);
createAttribute(globalAddressClass, "location", stringPrimitiveType, 1,
1);
createAttribute(globalLocationClass, "countryCode", intPrimitiveType,
1, 1);
banner("Creating associations between model classes.");
// Create associations between our classes.
createAssociation(supplierClass, true,
AggregationKind.COMPOSITE_LITERAL, "orders", 0,
LiteralUnlimitedNatural.UNLIMITED, purchaseOrderClass, false,
AggregationKind.NONE_LITERAL, "", 1, 1);
createAssociation(supplierClass, true, AggregationKind.NONE_LITERAL,
"pendingOrders", 0, LiteralUnlimitedNatural.UNLIMITED,
purchaseOrderClass, false, AggregationKind.NONE_LITERAL, "", 0, 1);
createAssociation(supplierClass, true, AggregationKind.NONE_LITERAL,
"shippedOrders", 0, LiteralUnlimitedNatural.UNLIMITED,
purchaseOrderClass, false, AggregationKind.NONE_LITERAL, "", 0, 1);
createAssociation(supplierClass, true,
AggregationKind.COMPOSITE_LITERAL, "customers", 0,
LiteralUnlimitedNatural.UNLIMITED, customerClass, false,
AggregationKind.NONE_LITERAL, "", 1, 1);
createAssociation(customerClass, true, AggregationKind.NONE_LITERAL,
"orders", 0, LiteralUnlimitedNatural.UNLIMITED, purchaseOrderClass,
true, AggregationKind.NONE_LITERAL, "customer", 1, 1);
createAssociation(purchaseOrderClass, true,
AggregationKind.NONE_LITERAL, "previousOrder", 0, 1,
purchaseOrderClass, false, AggregationKind.NONE_LITERAL, "", 0, 1);
createAssociation(purchaseOrderClass, true,
AggregationKind.COMPOSITE_LITERAL, "items", 0,
LiteralUnlimitedNatural.UNLIMITED, itemClass, true,
AggregationKind.NONE_LITERAL, "order", 1, 1);
createAssociation(purchaseOrderClass, true,
AggregationKind.COMPOSITE_LITERAL, "billTo", 1, 1, addressClass,
false, AggregationKind.NONE_LITERAL, "", 1, 1);
createAssociation(purchaseOrderClass, true,
AggregationKind.COMPOSITE_LITERAL, "shipTo", 1, 1, addressClass,
false, AggregationKind.NONE_LITERAL, "", 1, 1);
// Save our model to a file in the user-specified output directory
URI outputURI = URI.createFileURI(outputDir.getAbsolutePath())
.appendSegment("ExtendedPO2")
.appendFileExtension(UMLResource.FILE_EXTENSION);
banner("Saving the model to %s.", outputURI.toFileString());
save(epo2Model, outputURI);
}
//
// Model-building utilities
//
protected static Model createModel(String name) {
Model model = UMLFactory.eINSTANCE.createModel();
model.setName(name);
out("Model '%s' created.", model.getQualifiedName());
return model;
}
protected static org.eclipse.uml2.uml.Package createPackage(
org.eclipse.uml2.uml.Package nestingPackage, String name) {
org.eclipse.uml2.uml.Package package_ = nestingPackage
.createNestedPackage(name);
out("Package '%s' created.", package_.getQualifiedName());
return package_;
}
protected static PrimitiveType createPrimitiveType(
org.eclipse.uml2.uml.Package package_, String name) {
PrimitiveType primitiveType = package_.createOwnedPrimitiveType(name);
out("Primitive type '%s' created.", primitiveType.getQualifiedName());
return primitiveType;
}
protected static Enumeration createEnumeration(
org.eclipse.uml2.uml.Package package_, String name) {
Enumeration enumeration = package_.createOwnedEnumeration(name);
out("Enumeration '%s' created.", enumeration.getQualifiedName());
return enumeration;
}
protected static EnumerationLiteral createEnumerationLiteral(
Enumeration enumeration, String name) {
EnumerationLiteral enumerationLiteral = enumeration
.createOwnedLiteral(name);
out("Enumeration literal '%s' created.",
enumerationLiteral.getQualifiedName());
return enumerationLiteral;
}
protected static org.eclipse.uml2.uml.Class createClass(
org.eclipse.uml2.uml.Package package_, String name,
boolean isAbstract) {
org.eclipse.uml2.uml.Class class_ = package_.createOwnedClass(name,
isAbstract);
out("Class '%s' created.", class_.getQualifiedName());
return class_;
}
protected static Generalization createGeneralization(
Classifier specificClassifier, Classifier generalClassifier) {
Generalization generalization = specificClassifier
.createGeneralization(generalClassifier);
out("Generalization %s --|> %s created.",
specificClassifier.getQualifiedName(),
generalClassifier.getQualifiedName());
return generalization;
}
protected static Property createAttribute(
org.eclipse.uml2.uml.Class class_, String name, Type type,
int lowerBound, int upperBound) {
Property attribute = class_.createOwnedAttribute(name, type,
lowerBound, upperBound);
out("Attribute '%s' : %s [%s..%s] created.", //
attribute.getQualifiedName(), // attribute name
type.getQualifiedName(), // type name
lowerBound, // no special case for multiplicity lower bound
(upperBound == LiteralUnlimitedNatural.UNLIMITED)
? "*" // special case for unlimited bound
: upperBound);
return attribute;
}
protected static Association createAssociation(Type type1,
boolean end1IsNavigable, AggregationKind end1Aggregation,
String end1Name, int end1LowerBound, int end1UpperBound,
Type type2, boolean end2IsNavigable,
AggregationKind end2Aggregation, String end2Name,
int end2LowerBound, int end2UpperBound) {
Association association = type1.createAssociation(end1IsNavigable,
end1Aggregation, end1Name, end1LowerBound, end1UpperBound, type2,
end2IsNavigable, end2Aggregation, end2Name, end2LowerBound,
end2UpperBound);
out("Association %s [%s..%s] %s-%s %s [%s..%s] created.", //
UML2Util.isEmpty(end1Name)
// compute a placeholder for the name
? String.format("{%s}", type1.getQualifiedName()) //
// user-specified name
: String.format("'%s::%s'", type1.getQualifiedName(), end1Name), //
end1LowerBound, // no special case for this
(end1UpperBound == LiteralUnlimitedNatural.UNLIMITED)
? "*" // special case for unlimited upper bound
: end1UpperBound, // finite upper bound
end2IsNavigable
? "<" // indicate navigability
: "-", // not navigable
end1IsNavigable
? ">" // indicate navigability
: "-", // not navigable
UML2Util.isEmpty(end2Name)
// compute a placeholder for the name
? String.format("{%s}", type2.getQualifiedName()) //
// user-specified name
: String.format("'%s::%s'", type2.getQualifiedName(), end2Name), //
end2LowerBound, // no special case for this
(end2UpperBound == LiteralUnlimitedNatural.UNLIMITED)
? "*" // special case for unlimited upper bound
: end2UpperBound);
return association;
}
//
// Program control
//
private static boolean processArgs(String[] args)
throws IOException {
if (args.length != 1) {
err("Expected 1 argument.");
err("Usage: java -jar ... %s <dir>",
GettingStartedWithUML2.class.getSimpleName());
err("where");
err("<dir> - path to output folder in which to save the UML model");
return false;
}
outputDir = new File(args[0]).getCanonicalFile();
if (!outputDir.exists()) {
err("No such directory: %s", outputDir.getAbsolutePath());
return false;
}
if (!outputDir.isDirectory()) {
err("Not a directory: %s", outputDir.getAbsolutePath());
return false;
}
if (!outputDir.canWrite()) {
err("Cannot create a file in directory: %s",
outputDir.getAbsolutePath());
return false;
}
return true;
}
protected static void save(org.eclipse.uml2.uml.Package package_, URI uri) {
// Create a resource-set to contain the resource(s) that we are saving
ResourceSet resourceSet = new ResourceSetImpl();
// Initialize registrations of resource factories, library models,
// profiles, Ecore metadata, and other dependencies required for
// serializing and working with UML resources. This is only necessary in
// applications that are not hosted in the Eclipse platform run-time, in
// which case these registrations are discovered automatically from
// Eclipse extension points.
UMLResourcesUtil.init(resourceSet);
// Create the output resource and add our model package to it.
Resource resource = resourceSet.createResource(uri);
resource.getContents().add(package_);
// And save
try {
resource.save(null); // no save options needed
out("Done.");
} catch (IOException ioe) {
err(ioe.getMessage());
}
}
//
// Logging utilities
//
protected static void banner(String format, Object... args) {
System.out.println();
hrule();
System.out.printf(format, args);
if (!format.endsWith("%n")) {
System.out.println();
}
hrule();
System.out.println();
}
protected static void hrule() {
System.out.println("------------------------------------");
}
protected static void out(String format, Object... args) {
if (DEBUG) {
System.out.printf(format, args);
if (!format.endsWith("%n")) {
System.out.println();
}
}
}
protected static void err(String format, Object... args) {
System.err.printf(format, args);
if (!format.endsWith("%n")) {
System.err.println();
}
}
}