Source Code Cross Referenced for SchemaTransformer.java in  » UML » AndroMDA-3.2 » org » andromda » schema2xmi » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » UML » AndroMDA 3.2 » org.andromda.schema2xmi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.andromda.schema2xmi;
002:
003:        import java.sql.Connection;
004:        import java.sql.DatabaseMetaData;
005:        import java.sql.DriverManager;
006:        import java.sql.ResultSet;
007:        import java.sql.SQLException;
008:
009:        import java.util.ArrayList;
010:        import java.util.Collection;
011:        import java.util.HashMap;
012:        import java.util.HashSet;
013:        import java.util.Iterator;
014:        import java.util.Map;
015:
016:        import org.andromda.core.common.ExceptionUtils;
017:        import org.andromda.core.engine.ModelProcessorException;
018:        import org.andromda.core.mapping.Mappings;
019:        import org.andromda.core.namespace.NamespaceComponents;
020:        import org.andromda.core.repository.Repositories;
021:        import org.andromda.core.repository.RepositoryFacade;
022:        import org.apache.commons.dbutils.DbUtils;
023:        import org.apache.commons.lang.StringUtils;
024:        import org.apache.log4j.Logger;
025:        import org.omg.uml.UmlPackage;
026:        import org.omg.uml.foundation.core.AssociationEnd;
027:        import org.omg.uml.foundation.core.Attribute;
028:        import org.omg.uml.foundation.core.Classifier;
029:        import org.omg.uml.foundation.core.CorePackage;
030:        import org.omg.uml.foundation.core.DataType;
031:        import org.omg.uml.foundation.core.Stereotype;
032:        import org.omg.uml.foundation.core.TagDefinition;
033:        import org.omg.uml.foundation.core.TaggedValue;
034:        import org.omg.uml.foundation.core.UmlAssociation;
035:        import org.omg.uml.foundation.core.UmlClass;
036:        import org.omg.uml.foundation.datatypes.AggregationKindEnum;
037:        import org.omg.uml.foundation.datatypes.ChangeableKindEnum;
038:        import org.omg.uml.foundation.datatypes.DataTypesPackage;
039:        import org.omg.uml.foundation.datatypes.Multiplicity;
040:        import org.omg.uml.foundation.datatypes.MultiplicityRange;
041:        import org.omg.uml.foundation.datatypes.OrderingKindEnum;
042:        import org.omg.uml.foundation.datatypes.ScopeKindEnum;
043:        import org.omg.uml.foundation.datatypes.VisibilityKindEnum;
044:        import org.omg.uml.modelmanagement.Model;
045:        import org.omg.uml.modelmanagement.ModelManagementPackage;
046:
047:        /**
048:         * Performs the transformation of database schema to XMI.
049:         *
050:         * @todo This class really should have the functionality it uses (writing model
051:         *       elements) moved to the metafacades.
052:         * @todo This class should be refactored into smaller classes.
053:         * @author Chad Brandon
054:         */
055:        public class SchemaTransformer {
056:            private final static Logger logger = Logger
057:                    .getLogger(SchemaTransformer.class);
058:            private RepositoryFacade repository = null;
059:
060:            /**
061:             * The JDBC driver class
062:             */
063:            private String jdbcDriver = null;
064:
065:            /**
066:             * The JDBC schema user.
067:             */
068:            private String jdbcUser = null;
069:
070:            /**
071:             * The JDBC schema password.
072:             */
073:            private String jdbcPassword = null;
074:
075:            /**
076:             * The JDBC connection URL.
077:             */
078:            private String jdbcConnectionUrl = null;
079:
080:            /**
081:             * The name of the package in which the name of the elements will be
082:             * created.
083:             */
084:            private String packageName = null;
085:
086:            /**
087:             * Stores the name of the schema where the tables can be found.
088:             */
089:            private String schema = null;
090:
091:            /**
092:             * The regular expression pattern to match on when deciding what table names
093:             * to add to the transformed XMI.
094:             */
095:            private String tableNamePattern = null;
096:
097:            /**
098:             * Stores the schema types to model type mappings.
099:             */
100:            private Mappings typeMappings = null;
101:
102:            /**
103:             * Stores the classes keyed by table name.
104:             */
105:            private Map classes = new HashMap();
106:
107:            /**
108:             * Stores the foreign keys for each table.
109:             */
110:            private Map foreignKeys = new HashMap();
111:
112:            /**
113:             * Specifies the Class stereotype.
114:             */
115:            private String classStereotypes = null;
116:
117:            /**
118:             * Stores the name of the column tagged value to use for storing the name of
119:             * the column.
120:             */
121:            private String columnTaggedValue = null;
122:
123:            /**
124:             * Stores the name of the table tagged value to use for storing the name of
125:             * the table.
126:             */
127:            private String tableTaggedValue = null;
128:
129:            /**
130:             * Stores the version of XMI that will be produced.
131:             */
132:            private String xmiVersion = null;
133:
134:            /**
135:             * Constructs a new instance of this SchemaTransformer.
136:             */
137:            public SchemaTransformer(String jdbcDriver,
138:                    String jdbcConnectionUrl, String jdbcUser,
139:                    String jdbcPassword) {
140:                ExceptionUtils.checkEmpty("jdbcDriver", jdbcDriver);
141:                ExceptionUtils.checkEmpty("jdbcConnectionUrl",
142:                        jdbcConnectionUrl);
143:                ExceptionUtils.checkEmpty("jdbcUser", jdbcUser);
144:                ExceptionUtils.checkEmpty("jdbcPassword", jdbcPassword);
145:
146:                NamespaceComponents.instance().discover();
147:                Repositories.instance().initialize();
148:                this .repository = Repositories.instance().getImplementation(
149:                        Schema2XMIGlobals.REPOSITORY_NAMESPACE_NETBEANSMDR);
150:                if (repository == null) {
151:                    throw new ModelProcessorException(
152:                            "No Repository could be found, please make sure you have a repository with namespace "
153:                                    + Schema2XMIGlobals.REPOSITORY_NAMESPACE_NETBEANSMDR
154:                                    + " on your classpath");
155:                }
156:                this .repository.open();
157:
158:                this .jdbcDriver = jdbcDriver;
159:                this .jdbcConnectionUrl = jdbcConnectionUrl;
160:                this .jdbcUser = jdbcUser;
161:                this .jdbcPassword = jdbcPassword;
162:                this .jdbcConnectionUrl = jdbcConnectionUrl;
163:            }
164:
165:            /**
166:             * Transforms the Schema file and writes it to the location given by
167:             * <code>outputLocation</code>. The <code>inputModel</code> must be a
168:             * valid URL, otherwise an exception will be thrown.
169:             *
170:             * @param inputModel the location of the input model to start with (if there
171:             *        is one)
172:             * @param outputLocation The location to where the transformed output will
173:             *        be written.
174:             */
175:            public void transform(String inputModel, String outputLocation) {
176:                long startTime = System.currentTimeMillis();
177:                outputLocation = StringUtils.trimToEmpty(outputLocation);
178:                if (outputLocation == null) {
179:                    throw new IllegalArgumentException(
180:                            "'outputLocation' can not be null");
181:                }
182:                Connection connection = null;
183:                try {
184:                    if (inputModel != null) {
185:                        logger.info("Input model --> '" + inputModel + "'");
186:                    }
187:                    this .repository
188:                            .readModel(new String[] { inputModel }, null);
189:                    Class.forName(this .jdbcDriver);
190:                    connection = DriverManager.getConnection(
191:                            this .jdbcConnectionUrl, this .jdbcUser,
192:                            this .jdbcPassword);
193:                    repository.writeModel(transform(connection),
194:                            outputLocation, this .xmiVersion);
195:                } catch (Throwable th) {
196:                    throw new SchemaTransformerException(th);
197:                } finally {
198:                    DbUtils.closeQuietly(connection);
199:                    repository.close();
200:                }
201:                logger.info("Completed adding " + this .classes.size()
202:                        + " classes, writing model to --> '" + outputLocation
203:                        + "', TIME --> "
204:                        + ((System.currentTimeMillis() - startTime) / 1000.0)
205:                        + "[s]");
206:            }
207:
208:            /**
209:             * Sets the <code>mappingsUri</code> which is the URI to the sql types to
210:             * model type mappings.
211:             *
212:             * @param typeMappingsUri The typeMappings to set.
213:             */
214:            public void setTypeMappings(String typeMappingsUri) {
215:                try {
216:                    this .typeMappings = Mappings.getInstance(typeMappingsUri);
217:                } catch (final Throwable throwable) {
218:                    throw new SchemaTransformerException(throwable);
219:                }
220:            }
221:
222:            /**
223:             * Sets the name of the package to which the model elements will be created.
224:             *
225:             * @param packageName The packageName to set.
226:             */
227:            public void setPackageName(String packageName) {
228:                this .packageName = packageName;
229:            }
230:
231:            /**
232:             * Sets the name of the schema (where the tables can be found).
233:             *
234:             * @param schema The schema to set.
235:             */
236:            public void setSchema(String schema) {
237:                this .schema = schema;
238:            }
239:
240:            /**
241:             * Sets the regular expression pattern to match on when deciding what table
242:             * names to add to the transformed XMI.
243:             *
244:             * @param tableNamePattern The tableNamePattern to set.
245:             */
246:            public void setTableNamePattern(String tableNamePattern) {
247:                this .tableNamePattern = StringUtils
248:                        .trimToEmpty(tableNamePattern);
249:            }
250:
251:            /**
252:             * The column name pattern.
253:             */
254:            private String columnNamePattern;
255:
256:            /**
257:             * Sets the regular expression pattern to match on when deciding what attributes
258:             * ti create in the XMI.
259:             *
260:             * @param columnNamePattern The pattern for filtering the column name.
261:             */
262:            public void setColumnNamePattern(String columnNamePattern) {
263:                this .columnNamePattern = columnNamePattern;
264:            }
265:
266:            /**
267:             * Sets the stereotype name for the new classes.
268:             *
269:             * @param classStereotypes The classStereotypes to set.
270:             */
271:            public void setClassStereotypes(String classStereotypes) {
272:                this .classStereotypes = StringUtils
273:                        .deleteWhitespace(classStereotypes);
274:            }
275:
276:            /**
277:             * Specifies the identifier stereotype.
278:             */
279:            private String identifierStereotypes = null;
280:
281:            /**
282:             * Sets the stereotype name for the identifiers on the new classes.
283:             *
284:             * @param identifierStereotypes The identifierStereotypes to set.
285:             */
286:            public void setIdentifierStereotypes(String identifierStereotypes) {
287:                this .identifierStereotypes = StringUtils
288:                        .deleteWhitespace(identifierStereotypes);
289:            }
290:
291:            /**
292:             * Sets the name of the column tagged value to use for storing the name of
293:             * the column.
294:             *
295:             * @param columnTaggedValue The columnTaggedValue to set.
296:             */
297:            public void setColumnTaggedValue(String columnTaggedValue) {
298:                this .columnTaggedValue = StringUtils
299:                        .trimToEmpty(columnTaggedValue);
300:            }
301:
302:            /**
303:             * Sets the name of the table tagged value to use for storing the name of
304:             * the table.
305:             *
306:             * @param tableTaggedValue The tableTaggedValue to set.
307:             */
308:            public void setTableTaggedValue(String tableTaggedValue) {
309:                this .tableTaggedValue = StringUtils
310:                        .trimToEmpty(tableTaggedValue);
311:            }
312:
313:            /**
314:             * Sets the version of XMI that will be produced.
315:             *
316:             * @param xmiVersion The xmiVersion to set.
317:             */
318:            public void setXmiVersion(String xmiVersion) {
319:                this .xmiVersion = xmiVersion;
320:            }
321:
322:            /**
323:             * The package that is currently being processed.
324:             */
325:            private UmlPackage umlPackage;
326:
327:            /**
328:             * The model thats currently being processed
329:             */
330:            private Model model;
331:
332:            /**
333:             * Performs the actual translation of the Schema to the XMI and returns the
334:             * object model.
335:             */
336:            private final Object transform(final Connection connection)
337:                    throws Exception {
338:                this .umlPackage = (UmlPackage) this .repository.getModel()
339:                        .getModel();
340:
341:                final ModelManagementPackage modelManagementPackage = umlPackage
342:                        .getModelManagement();
343:
344:                final Collection models = modelManagementPackage.getModel()
345:                        .refAllOfType();
346:                if (models != null && !models.isEmpty()) {
347:                    // A given XMI file can contain multiple models.
348:                    // Use the first model in the XMI file
349:                    this .model = (Model) models.iterator().next();
350:                } else {
351:                    this .model = modelManagementPackage.getModel()
352:                            .createModel();
353:                }
354:
355:                // create the package on the model
356:                org.omg.uml.modelmanagement.UmlPackage leafPackage = this 
357:                        .getOrCreatePackage(umlPackage.getModelManagement(),
358:                                model, this .packageName);
359:                this .createClasses(connection, umlPackage.getModelManagement()
360:                        .getCore(), leafPackage);
361:
362:                return umlPackage;
363:            }
364:
365:            /**
366:             * Gets or creates a package having the specified <code>packageName</code>
367:             * using the given <code>modelManagementPackage</code>, places it on the
368:             * <code>model</code> and returns the last leaf package.
369:             *
370:             * @param modelManagementPackage from which we retrieve the UmlPackageClass
371:             *        to create a UmlPackage.
372:             * @param modelPackage the root UmlPackage
373:             */
374:            protected org.omg.uml.modelmanagement.UmlPackage getOrCreatePackage(
375:                    ModelManagementPackage modelManagementPackage,
376:                    org.omg.uml.modelmanagement.UmlPackage modelPackage,
377:                    String packageName) {
378:                packageName = StringUtils.trimToEmpty(packageName);
379:                if (StringUtils.isNotEmpty(packageName)) {
380:                    String[] packages = packageName
381:                            .split(Schema2XMIGlobals.PACKAGE_SEPERATOR);
382:                    if (packages != null && packages.length > 0) {
383:                        for (int ctr = 0; ctr < packages.length; ctr++) {
384:                            Object umlPackage = ModelElementFinder.find(
385:                                    modelPackage, packages[ctr]);
386:
387:                            if (umlPackage == null) {
388:                                umlPackage = modelManagementPackage
389:                                        .getUmlPackage().createUmlPackage(
390:                                                packages[ctr],
391:                                                VisibilityKindEnum.VK_PUBLIC,
392:                                                false, false, false, false);
393:                                modelPackage.getOwnedElement().add(umlPackage);
394:                            }
395:                            modelPackage = (org.omg.uml.modelmanagement.UmlPackage) umlPackage;
396:                        }
397:                    }
398:                }
399:                return modelPackage;
400:            }
401:
402:            /**
403:             * Creates all classes from the tables found in the schema.
404:             *
405:             * @param connection the Connection used to retrieve the schema metadata.
406:             * @param corePackage the CorePackage instance we use to create the classes.
407:             * @param modelPackage the package which the classes are added.
408:             */
409:            protected void createClasses(Connection connection,
410:                    CorePackage corePackage,
411:                    org.omg.uml.modelmanagement.UmlPackage modelPackage)
412:                    throws SQLException {
413:                DatabaseMetaData metadata = connection.getMetaData();
414:                ResultSet tableRs = metadata.getTables(null, this .schema, null,
415:                        new String[] { "TABLE" });
416:
417:                // loop through and create all classes and store then
418:                // in the classes Map keyed by table
419:                while (tableRs.next()) {
420:                    String tableName = tableRs.getString("TABLE_NAME");
421:                    if (StringUtils.isNotBlank(this .tableNamePattern)) {
422:                        if (tableName.matches(this .tableNamePattern)) {
423:                            UmlClass umlClass = this .createClass(modelPackage,
424:                                    metadata, corePackage, tableName);
425:                            this .classes.put(tableName, umlClass);
426:                        }
427:                    } else {
428:                        UmlClass umlClass = this .createClass(modelPackage,
429:                                metadata, corePackage, tableName);
430:                        this .classes.put(tableName, umlClass);
431:                    }
432:                }
433:                DbUtils.closeQuietly(tableRs);
434:                if (this .classes.isEmpty()) {
435:                    String schemaName = "";
436:                    if (StringUtils.isNotEmpty(this .schema)) {
437:                        schemaName = " '" + this .schema + "' ";
438:                    }
439:                    StringBuffer warning = new StringBuffer(
440:                            "WARNING! No tables found in schema");
441:                    warning.append(schemaName);
442:                    if (StringUtils.isNotEmpty(this .tableNamePattern)) {
443:                        warning.append(" matching pattern --> '"
444:                                + this .tableNamePattern + "'");
445:                    }
446:                    logger.warn(warning);
447:                }
448:
449:                // add all attributes and associations to the modelPackage
450:                Iterator tableNameIt = this .classes.keySet().iterator();
451:                while (tableNameIt.hasNext()) {
452:                    String tableName = (String) tableNameIt.next();
453:                    UmlClass umlClass = (UmlClass) classes.get(tableName);
454:                    if (logger.isInfoEnabled()) {
455:                        logger.info("created class --> '" + umlClass.getName()
456:                                + "'");
457:                    }
458:
459:                    // create and add all associations to the package
460:                    modelPackage.getOwnedElement().addAll(
461:                            this .createAssociations(metadata, corePackage,
462:                                    tableName));
463:
464:                    // create and add all the attributes
465:                    umlClass.getFeature().addAll(
466:                            this .createAttributes(metadata, corePackage,
467:                                    tableName));
468:
469:                    modelPackage.getOwnedElement().add(umlClass);
470:                }
471:            }
472:
473:            /**
474:             * Creates and returns a UmlClass with the given <code>name</code> using
475:             * the <code>corePackage</code> to create it.
476:             *
477:             * @param corePackage used to create the class.
478:             * @param tableName to tableName for which we'll create the appropriate
479:             *        class.
480:             * @return the UmlClass
481:             */
482:            protected UmlClass createClass(
483:                    org.omg.uml.modelmanagement.UmlPackage modelPackage,
484:                    DatabaseMetaData metadata, CorePackage corePackage,
485:                    String tableName) {
486:                String className = SqlToModelNameFormatter
487:                        .toClassName(tableName);
488:                UmlClass umlClass = corePackage.getUmlClass().createUmlClass(
489:                        className, VisibilityKindEnum.VK_PUBLIC, false, false,
490:                        false, false, false);
491:
492:                umlClass.getStereotype().addAll(
493:                        this .getOrCreateStereotypes(corePackage,
494:                                this .classStereotypes, "Classifier"));
495:
496:                if (StringUtils.isNotEmpty(this .tableTaggedValue)) {
497:                    // add the tagged value for the table name
498:                    TaggedValue taggedValue = this .createTaggedValue(
499:                            corePackage, this .tableTaggedValue, tableName);
500:                    if (taggedValue != null) {
501:                        umlClass.getTaggedValue().add(taggedValue);
502:                    }
503:                }
504:
505:                return umlClass;
506:            }
507:
508:            /**
509:             * Creates and returns a collection of attributes from creating an attribute
510:             * from every column on the table having the give <code>tableName</code>.
511:             *
512:             * @param metadata the DatabaseMetaData from which to retrieve the columns.
513:             * @param corePackage used to create the class.
514:             * @param tableName the tableName for which to find columns.
515:             * @return the collection of new attributes.
516:             */
517:            protected Collection createAttributes(DatabaseMetaData metadata,
518:                    CorePackage corePackage, String tableName)
519:                    throws SQLException {
520:                final Collection attributes = new ArrayList();
521:                final ResultSet columnRs = metadata.getColumns(null,
522:                        this .schema, tableName, null);
523:                final Collection primaryKeyColumns = this .getPrimaryKeyColumns(
524:                        metadata, tableName);
525:                while (columnRs.next()) {
526:                    final String columnName = columnRs.getString("COLUMN_NAME");
527:                    if (this .columnNamePattern == null
528:                            || columnName.matches(this .columnNamePattern)) {
529:                        final String attributeName = SqlToModelNameFormatter
530:                                .toAttributeName(columnName);
531:                        if (logger.isInfoEnabled()) {
532:                            logger.info("adding attribute --> '"
533:                                    + attributeName + "'");
534:                        }
535:
536:                        // do NOT add foreign key columns as attributes (since
537:                        // they are placed on association ends)
538:                        if (!this .hasForeignKey(tableName, columnName)) {
539:                            Classifier typeClass = null;
540:
541:                            // first we try to find a mapping that maps to the
542:                            // database proprietary type
543:                            String type = Schema2XMIUtils.constructTypeName(
544:                                    columnRs.getString("TYPE_NAME"), columnRs
545:                                            .getString("COLUMN_SIZE"));
546:                            logger.info("  -  searching for type mapping '"
547:                                    + type + "'");
548:                            if (typeMappings.containsFrom(type)) {
549:                                typeClass = this .getOrCreateDataType(
550:                                        corePackage, type);
551:                            }
552:
553:                            // - See if we can find a type matching a mapping for a JDBC type 
554:                            //   (if we haven't found a database specific one)
555:                            if (typeClass == null) {
556:                                type = JdbcTypeFinder.find(columnRs
557:                                        .getInt("DATA_TYPE"));
558:                                logger.info("  -  searching for type mapping '"
559:                                        + type + "'");
560:                                if (typeMappings.containsFrom(type)) {
561:                                    typeClass = this .getOrCreateDataType(
562:                                            corePackage, type);
563:                                } else {
564:                                    logger
565:                                            .info("  !  no mapping found, type not added to '"
566:                                                    + attributeName + "'");
567:                                }
568:                            }
569:
570:                            boolean required = !this .isColumnNullable(metadata,
571:                                    tableName, columnName);
572:
573:                            Attribute attribute = corePackage
574:                                    .getAttribute()
575:                                    .createAttribute(
576:                                            attributeName,
577:                                            VisibilityKindEnum.VK_PUBLIC,
578:                                            false,
579:                                            ScopeKindEnum.SK_INSTANCE,
580:                                            this .createAttributeMultiplicity(
581:                                                    corePackage.getDataTypes(),
582:                                                    required),
583:                                            ChangeableKindEnum.CK_CHANGEABLE,
584:                                            ScopeKindEnum.SK_CLASSIFIER,
585:                                            OrderingKindEnum.OK_UNORDERED, null);
586:                            attribute.setType(typeClass);
587:
588:                            if (StringUtils.isNotEmpty(this .columnTaggedValue)) {
589:                                // add the tagged value for the column name
590:                                TaggedValue taggedValue = this 
591:                                        .createTaggedValue(corePackage,
592:                                                this .columnTaggedValue,
593:                                                columnName);
594:                                if (taggedValue != null) {
595:                                    attribute.getTaggedValue().add(taggedValue);
596:                                }
597:                            }
598:                            if (primaryKeyColumns.contains(columnName)) {
599:                                attribute.getStereotype().addAll(
600:                                        this .getOrCreateStereotypes(
601:                                                corePackage,
602:                                                this .identifierStereotypes,
603:                                                "Attribute"));
604:                            }
605:                            attributes.add(attribute);
606:                        }
607:                    }
608:                }
609:                DbUtils.closeQuietly(columnRs);
610:                return attributes;
611:            }
612:
613:            /**
614:             * Gets or creates a new data type instance having the given fully qualified
615:             * <code>type</code> name.
616:             *
617:             * @param corePackage the core package
618:             * @param type the fully qualified type name.
619:             * @return the DataType
620:             */
621:            protected DataType getOrCreateDataType(CorePackage corePackage,
622:                    String type) {
623:                type = this .typeMappings.getTo(type);
624:                Object datatype = ModelElementFinder.find(this .model, type);
625:                if (datatype == null
626:                        || !DataType.class
627:                                .isAssignableFrom(datatype.getClass())) {
628:                    String[] names = type
629:                            .split(Schema2XMIGlobals.PACKAGE_SEPERATOR);
630:                    if (names != null && names.length > 0) {
631:                        // the last name is the type name
632:                        String typeName = names[names.length - 1];
633:                        names[names.length - 1] = null;
634:                        String packageName = StringUtils.join(names,
635:                                Schema2XMIGlobals.PACKAGE_SEPERATOR);
636:                        org.omg.uml.modelmanagement.UmlPackage umlPackage = this 
637:                                .getOrCreatePackage(this .umlPackage
638:                                        .getModelManagement(), this .model,
639:                                        packageName);
640:                        if (umlPackage != null) {
641:                            datatype = corePackage.getDataType()
642:                                    .createDataType(typeName,
643:                                            VisibilityKindEnum.VK_PUBLIC,
644:                                            false, false, false, false);
645:                            umlPackage.getOwnedElement().add(datatype);
646:                        }
647:                    }
648:                }
649:                return (DataType) datatype;
650:            }
651:
652:            /**
653:             * This method just checks to see if a column is null able or not, if so,
654:             * returns true, if not returns false.
655:             *
656:             * @param metadata the DatabaseMetaData instance used to retrieve the column
657:             *        information.
658:             * @param tableName the name of the table on which the column exists.
659:             * @param columnName the name of the column.
660:             * @param true/false on whether or not column is nullable.
661:             */
662:            protected boolean isColumnNullable(DatabaseMetaData metadata,
663:                    String tableName, String columnName) throws SQLException {
664:                boolean nullable = true;
665:                ResultSet columnRs = metadata.getColumns(null, this .schema,
666:                        tableName, columnName);
667:                while (columnRs.next()) {
668:                    nullable = columnRs.getInt("NULLABLE") != DatabaseMetaData.attributeNoNulls;
669:                }
670:                DbUtils.closeQuietly(columnRs);
671:                return nullable;
672:            }
673:
674:            /**
675:             * Returns a collection of all primary key column names for the given
676:             * <code>tableName</code>.
677:             *
678:             * @param metadata
679:             * @param tableName
680:             * @return collection of primary key names.
681:             */
682:            protected Collection getPrimaryKeyColumns(
683:                    DatabaseMetaData metadata, String tableName)
684:                    throws SQLException {
685:                Collection primaryKeys = new HashSet();
686:                ResultSet primaryKeyRs = metadata.getPrimaryKeys(null,
687:                        this .schema, tableName);
688:                while (primaryKeyRs.next()) {
689:                    primaryKeys.add(primaryKeyRs.getString("COLUMN_NAME"));
690:                }
691:                DbUtils.closeQuietly(primaryKeyRs);
692:                return primaryKeys;
693:            }
694:
695:            /**
696:             * Creates and returns a collection of associations by determing foreign
697:             * tables to the table having the given <code>tableName</code>.
698:             *
699:             * @param metadata the DatabaseMetaData from which to retrieve the columns.
700:             * @param corePackage used to create the class.
701:             * @param tableName the tableName for which to find columns.
702:             * @return the collection of new attributes.
703:             */
704:            protected Collection createAssociations(DatabaseMetaData metadata,
705:                    CorePackage corePackage, String tableName)
706:                    throws SQLException {
707:                Collection primaryKeys = this .getPrimaryKeyColumns(metadata,
708:                        tableName);
709:                Collection associations = new ArrayList();
710:                ResultSet columnRs = metadata.getImportedKeys(null,
711:                        this .schema, tableName);
712:                while (columnRs.next()) {
713:                    // store the foreign key in the foreignKeys Map
714:                    String fkColumnName = columnRs.getString("FKCOLUMN_NAME");
715:                    this .addForeignKey(tableName, fkColumnName);
716:
717:                    // now create the association
718:                    String foreignTableName = columnRs
719:                            .getString("PKTABLE_NAME");
720:                    UmlAssociation association = corePackage
721:                            .getUmlAssociation().createUmlAssociation(null,
722:                                    VisibilityKindEnum.VK_PUBLIC, false, false,
723:                                    false, false);
724:
725:                    // we set the upper range to 1 if the
726:                    // they primary key of this table is the
727:                    // foreign key of another table (by default
728:                    // its set to a many multiplicity)
729:                    int primaryUpper = -1;
730:                    if (primaryKeys.contains(fkColumnName)) {
731:                        primaryUpper = 1;
732:                    }
733:
734:                    String endName = null;
735:
736:                    // primary association
737:                    AssociationEnd primaryEnd = corePackage.getAssociationEnd()
738:                            .createAssociationEnd(
739:                                    endName,
740:                                    VisibilityKindEnum.VK_PUBLIC,
741:                                    false,
742:                                    true,
743:                                    OrderingKindEnum.OK_UNORDERED,
744:                                    AggregationKindEnum.AK_NONE,
745:                                    ScopeKindEnum.SK_INSTANCE,
746:                                    this .createMultiplicity(corePackage
747:                                            .getDataTypes(), 0, primaryUpper),
748:                                    ChangeableKindEnum.CK_CHANGEABLE);
749:                    primaryEnd.setParticipant((Classifier) this .classes
750:                            .get(tableName));
751:                    association.getConnection().add(primaryEnd);
752:
753:                    boolean required = !this .isColumnNullable(metadata,
754:                            tableName, fkColumnName);
755:
756:                    int foreignLower = 0;
757:                    if (required) {
758:                        foreignLower = 1;
759:                    }
760:
761:                    int deleteRule = columnRs.getInt("DELETE_RULE");
762:
763:                    // determine if we should have composition for
764:                    // the foreign association end depending on cascade delete
765:                    AggregationKindEnum foreignAggregation = AggregationKindEnum.AK_NONE;
766:                    if (deleteRule == DatabaseMetaData.importedKeyCascade) {
767:                        foreignAggregation = AggregationKindEnum.AK_COMPOSITE;
768:                    }
769:
770:                    // foriegn association
771:                    AssociationEnd foreignEnd = corePackage.getAssociationEnd()
772:                            .createAssociationEnd(
773:                                    endName,
774:                                    VisibilityKindEnum.VK_PUBLIC,
775:                                    false,
776:                                    true,
777:                                    OrderingKindEnum.OK_UNORDERED,
778:                                    foreignAggregation,
779:                                    ScopeKindEnum.SK_INSTANCE,
780:                                    this .createMultiplicity(corePackage
781:                                            .getDataTypes(), foreignLower, 1),
782:                                    ChangeableKindEnum.CK_CHANGEABLE);
783:                    final Classifier foreignParticipant = (Classifier) this .classes
784:                            .get(foreignTableName);
785:                    if (foreignParticipant == null) {
786:                        throw new SchemaTransformerException(
787:                                "The associated table '"
788:                                        + foreignTableName
789:                                        + "' must be available in order to create the association");
790:                    }
791:                    foreignEnd.setParticipant(foreignParticipant);
792:
793:                    if (StringUtils.isNotEmpty(this .columnTaggedValue)) {
794:                        // add the tagged value for the foreign association end
795:                        TaggedValue taggedValue = this .createTaggedValue(
796:                                corePackage, this .columnTaggedValue,
797:                                fkColumnName);
798:                        if (taggedValue != null) {
799:                            foreignEnd.getTaggedValue().add(taggedValue);
800:                        }
801:                    }
802:
803:                    association.getConnection().add(foreignEnd);
804:                    associations.add(association);
805:
806:                    if (logger.isInfoEnabled()) {
807:                        logger.info("adding association: '"
808:                                + primaryEnd.getParticipant().getName()
809:                                + " <--> "
810:                                + foreignEnd.getParticipant().getName() + "'");
811:                    }
812:                }
813:                DbUtils.closeQuietly(columnRs);
814:                return associations;
815:            }
816:
817:            /**
818:             * Creates a tagged value given the specfied <code>name</code>.
819:             *
820:             * @param name the name of the tagged value to create.
821:             * @param value the value to populate on the tagged value.
822:             * @return returns the new TaggedValue
823:             */
824:            protected TaggedValue createTaggedValue(CorePackage corePackage,
825:                    String name, String value) {
826:                Collection values = new HashSet();
827:                values.add(value);
828:                TaggedValue taggedValue = corePackage.getTaggedValue()
829:                        .createTaggedValue(name, VisibilityKindEnum.VK_PUBLIC,
830:                                false, values);
831:
832:                // see if we can find the tag defintion and if so add that
833:                // as the type.
834:                Object tagDefinition = ModelElementFinder.find(this .umlPackage,
835:                        name);
836:                if (tagDefinition != null
837:                        && TagDefinition.class.isAssignableFrom(tagDefinition
838:                                .getClass())) {
839:                    taggedValue.setType((TagDefinition) tagDefinition);
840:                }
841:                return taggedValue;
842:            }
843:
844:            /**
845:             * Gets or creates a stereotypes given the specfied comma seperated list of
846:             * <code>names</code>. If any of the stereotypes can't be found, they
847:             * will be created.
848:             *
849:             * @param names comma seperated list of stereotype names
850:             * @param baseClass the base class for which the stereotype applies.
851:             * @return Collection of Stereotypes
852:             */
853:            protected Collection getOrCreateStereotypes(
854:                    CorePackage corePackage, String names, String baseClass) {
855:                Collection stereotypes = new HashSet();
856:                String[] stereotypeNames = null;
857:                if (names != null) {
858:                    stereotypeNames = names.split(",");
859:                }
860:                if (stereotypeNames != null && stereotypeNames.length > 0) {
861:                    for (int ctr = 0; ctr < stereotypeNames.length; ctr++) {
862:                        String name = StringUtils
863:                                .trimToEmpty(stereotypeNames[ctr]);
864:
865:                        // see if we can find the stereotype first
866:                        Object stereotype = ModelElementFinder.find(
867:                                this .umlPackage, name);
868:                        if (stereotype == null
869:                                || !Stereotype.class
870:                                        .isAssignableFrom(stereotype.getClass())) {
871:                            Collection baseClasses = new ArrayList();
872:                            baseClasses.add(baseClass);
873:                            stereotype = corePackage.getStereotype()
874:                                    .createStereotype(name,
875:                                            VisibilityKindEnum.VK_PUBLIC,
876:                                            false, false, false, false, null,
877:                                            baseClasses);
878:                            this .model.getOwnedElement().add(stereotype);
879:                        }
880:                        stereotypes.add(stereotype);
881:                    }
882:                }
883:                return stereotypes;
884:            }
885:
886:            /**
887:             * Adds a foreign key column name to the <code>foreignKeys</code> Map. The
888:             * map stores a collection of foreign key names keyed by the given
889:             * <code>tableName</code>
890:             *
891:             * @param tableName the name of the table for which to store the keys.
892:             * @param columnName the name of the foreign key column name.
893:             */
894:            protected void addForeignKey(String tableName, String columnName) {
895:                if (StringUtils.isNotBlank(tableName)
896:                        && StringUtils.isNotBlank(columnName)) {
897:                    Collection foreignKeys = (Collection) this .foreignKeys
898:                            .get(tableName);
899:                    if (foreignKeys == null) {
900:                        foreignKeys = new HashSet();
901:                    }
902:                    foreignKeys.add(columnName);
903:                    this .foreignKeys.put(tableName, foreignKeys);
904:                }
905:            }
906:
907:            /**
908:             * Returns true if the table with the given <code>tableName</code> has a
909:             * foreign key with the specified <code>columnName</code>.
910:             *
911:             * @param tableName the name of the table to check for the foreign key
912:             * @param columnName the naem of the foreign key column.
913:             * @return true/false dependeing on whether or not the table has the foreign
914:             *         key with the given <code>columnName</code>.
915:             */
916:            protected boolean hasForeignKey(String tableName, String columnName) {
917:                boolean hasForeignKey = false;
918:                if (StringUtils.isNotBlank(tableName)
919:                        && StringUtils.isNotBlank(columnName)) {
920:                    Collection foreignKeys = (Collection) this .foreignKeys
921:                            .get(tableName);
922:                    if (foreignKeys != null) {
923:                        hasForeignKey = foreignKeys.contains(columnName);
924:                    }
925:                }
926:                return hasForeignKey;
927:            }
928:
929:            /**
930:             * Creates an attributes multiplicity, if <code>required</code> is true,
931:             * then multiplicity is set to 1, if <code>required</code> is false, then
932:             * multiplicity is set to 0..1.
933:             *
934:             * @param dataTypes used to create the Multiplicity
935:             * @param required whether or not the attribute is required therefore
936:             *        determining the multiplicity value created.
937:             * @return the new Multiplicity
938:             */
939:            protected Multiplicity createAttributeMultiplicity(
940:                    DataTypesPackage dataTypes, boolean required) {
941:                Multiplicity mult = null;
942:                if (required) {
943:                    mult = this .createMultiplicity(dataTypes, 1, 1);
944:                } else {
945:                    mult = this .createMultiplicity(dataTypes, 0, 1);
946:                }
947:                return mult;
948:            }
949:
950:            /**
951:             * Creates a multiplicity, from <code>lower</code> and <code>upper</code>
952:             * ranges.
953:             *
954:             * @param dataTypes used to create the Multiplicity
955:             * @param lower the lower range of the multiplicity
956:             * @param upper the upper range of the multiplicity
957:             * @return the new Multiplicity
958:             */
959:            protected Multiplicity createMultiplicity(
960:                    DataTypesPackage dataTypes, int lower, int upper) {
961:                Multiplicity mult = dataTypes.getMultiplicity()
962:                        .createMultiplicity();
963:                MultiplicityRange range = dataTypes.getMultiplicityRange()
964:                        .createMultiplicityRange(lower, upper);
965:                mult.getRange().add(range);
966:                return mult;
967:            }
968:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.