1 /* 2 3 dsh-codegen Source code generation suite. 4 Copyright (c) 2004-2013 held jointly by the individual authors. 5 6 This library is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 3 of the License, or (at 9 your option) any later version. 10 11 This library is distributed in the hope that it will be useful, but WITHOUT 12 ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this library; if not, write to the Free Software Foundation, 18 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 19 20 > http://www.fsf.org/licensing/licenses/lgpl.html 21 > http://www.opensource.org/licenses/lgpl-license.php 22 23 */ 24 package org.dishevelled.codegen; 25 26 import java.util.Set; 27 import java.util.LinkedHashSet; 28 import java.util.Collections; 29 30 /** 31 * A description of the attributes and associations for an interface. 32 * 33 * @author Michael Heuer 34 */ 35 public final class InterfaceDescription 36 { 37 /** License for this interface description. */ 38 private String license; 39 40 /** Package name for this interface description. */ 41 private String packageName; 42 43 /** Lowercase name for this interface description. */ 44 private String lower; 45 46 /** Mixed-case name for this interface description. */ 47 private String mixed; 48 49 /** Uppercase name for this interface description. */ 50 private String upper; 51 52 /** Author for this interface description. */ 53 private String author; 54 55 /** Version for this interface description. */ 56 private String version; 57 58 /** Description for this interface description. */ 59 private String description; 60 61 /** Set of interfaces this interface description specializes. */ 62 private final Set<InterfaceDescription> specializes; 63 64 /** Set of attributes for this interface description. */ 65 private final Set<Attribute> attributes; 66 67 /** Set of associations for this interface description. */ 68 private final Set<Association> associations; 69 70 71 /** 72 * Create a new interface description with the specified package name 73 * and name. 74 * 75 * @param packageName package name for this interface description 76 * @param name name of this interface description 77 */ 78 public InterfaceDescription(final String packageName, final String name) 79 { 80 this.packageName = packageName; 81 this.lower = CodegenUtils.makeLowercase(name); 82 this.mixed = CodegenUtils.makeMixedCase(name); 83 this.upper = CodegenUtils.makeUppercase(name); 84 this.description = CodegenUtils.makeSentenceCaseDescription(name); 85 this.author = "codegen"; 86 this.version = "$" + "Revision$ $" + "Date$"; // split to prevent svn expansion 87 this.specializes = new LinkedHashSet<InterfaceDescription>(); 88 this.attributes = new LinkedHashSet<Attribute>(); 89 this.associations = new LinkedHashSet<Association>(); 90 } 91 92 /** 93 * Create a new interface description with the specified package name 94 * and name. 95 * 96 * @param license license for this interface description 97 * @param packageName package name for this interface description 98 * @param name name of this interface description 99 */ 100 public InterfaceDescription(final String license, final String packageName, final String name) 101 { 102 this.license = license; 103 this.packageName = packageName; 104 this.lower = CodegenUtils.makeLowercase(name); 105 this.mixed = CodegenUtils.makeMixedCase(name); 106 this.upper = CodegenUtils.makeUppercase(name); 107 this.description = CodegenUtils.makeSentenceCaseDescription(name); 108 this.author = "codegen"; 109 this.version = "$" + "Revision$ $" + "Date$"; // split to prevent svn expansion 110 this.specializes = new LinkedHashSet<InterfaceDescription>(); 111 this.attributes = new LinkedHashSet<Attribute>(); 112 this.associations = new LinkedHashSet<Association>(); 113 } 114 115 /** 116 * Create a new interface description from the specified parameters. 117 * 118 * @param packageName package name for this interface description 119 * @param name uppercase name for this interface description 120 * @param author author for this interface description 121 * @param version version for this interface description 122 * @param description description for this interface description 123 */ 124 public InterfaceDescription(final String packageName, final String name, 125 final String author, final String version, final String description) 126 { 127 this.packageName = packageName; 128 this.lower = CodegenUtils.makeLowercase(name); 129 this.mixed = CodegenUtils.makeMixedCase(name); 130 this.upper = CodegenUtils.makeUppercase(name); 131 this.author = author; 132 this.version = version; 133 this.description = CodegenUtils.makeSentenceCaseDescription(name) + "."; 134 this.specializes = new LinkedHashSet<InterfaceDescription>(); 135 this.attributes = new LinkedHashSet<Attribute>(); 136 this.associations = new LinkedHashSet<Association>(); 137 } 138 139 /** 140 * Create a new interface description from the specified parameters. 141 * 142 * @param packageName package name for this interface description 143 * @param lower lowercase name for this interface description 144 * @param mixed mixed-case name for this interface description 145 * @param upper uppercase name for this interface description 146 * @param author author for this interface description 147 * @param version version for this interface description 148 * @param description description for this interface description 149 */ 150 public InterfaceDescription(final String packageName, final String lower, final String mixed, final String upper, 151 final String author, final String version, final String description) 152 { 153 this.packageName = packageName; 154 this.lower = lower; 155 this.mixed = mixed; 156 this.upper = upper; 157 this.author = author; 158 this.version = version; 159 this.description = description; 160 this.specializes = new LinkedHashSet<InterfaceDescription>(); 161 this.attributes = new LinkedHashSet<Attribute>(); 162 this.associations = new LinkedHashSet<Association>(); 163 } 164 165 /** 166 * Create a new interface description from the specified parameters. 167 * 168 * <p>The interfaces this interface description specializes in <code>specializes</code> are copied defensively 169 * into this class.</p> 170 * 171 * <p>The attributes in <code>attributes</code> are copied defensively 172 * into this class.</p> 173 * 174 * <p>The associations in <code>associations</code> are copied defensively 175 * into this class.</p> 176 * 177 * @param packageName package name for this interface description 178 * @param lower lowercase name for this interface description 179 * @param mixed mixed-case name for this interface description 180 * @param upper uppercase name for this interface description 181 * @param author author for this interface description 182 * @param version version for this interface description 183 * @param description description for this interface description 184 * @param specializes set of interfaces this interface description specializes, must not be null 185 * @param attributes set of attributes, must not be null 186 * @param associations set of associations, must not be null 187 */ 188 public InterfaceDescription(final String packageName, 189 final String lower, 190 final String mixed, 191 final String upper, 192 final String author, 193 final String version, 194 final String description, 195 final Set<InterfaceDescription> specializes, 196 final Set<Attribute> attributes, 197 final Set<Association> associations) 198 { 199 this.packageName = packageName; 200 this.lower = lower; 201 this.mixed = mixed; 202 this.upper = upper; 203 this.author = author; 204 this.version = version; 205 this.description = description; 206 207 this.specializes = new LinkedHashSet<InterfaceDescription>(specializes.size()); 208 this.specializes.addAll(specializes); 209 210 this.attributes = new LinkedHashSet<Attribute>(attributes.size()); 211 this.attributes.addAll(attributes); 212 213 this.associations = new LinkedHashSet<Association>(associations.size()); 214 this.associations.addAll(associations); 215 } 216 217 218 /** 219 * Return the license for this interface description. 220 * 221 * @return the license for this interface description 222 */ 223 public String getLicense() 224 { 225 return license; 226 } 227 228 /** 229 * Return the package name for this interface description. 230 * 231 * @return the package name for this interface description 232 */ 233 public String getPackageName() 234 { 235 return packageName; 236 } 237 238 /** 239 * Return the lowercase name for this interface description. 240 * 241 * @return the lowercase name for this interface description 242 */ 243 public String getLower() 244 { 245 return lower; 246 } 247 248 /** 249 * Return the mixed-case name for this interface description. 250 * 251 * @return the mixed-case name for this interface description 252 */ 253 public String getMixed() 254 { 255 return mixed; 256 } 257 258 /** 259 * Return the uppercase name for this interface description. 260 * 261 * @return the uppercase name for this interface description 262 */ 263 public String getUpper() 264 { 265 return upper; 266 } 267 268 /** 269 * Return the author for this interface description. 270 * 271 * @return the author for this interface description 272 */ 273 public String getAuthor() 274 { 275 return author; 276 } 277 278 /** 279 * Return the version for this interface description. 280 * 281 * @return the version for this interface description 282 */ 283 public String getVersion() 284 { 285 return version; 286 } 287 288 /** 289 * Return the description for this interface description. 290 * 291 * @return the description for this interface description 292 */ 293 public String getDescription() 294 { 295 return description; 296 } 297 298 /** 299 * Return an unmodifiable set of interfaces this interface description specializes. 300 * 301 * @return an unmodifiable set of interfaces this interface description specializes 302 */ 303 public Set<InterfaceDescription> getSpecializes() 304 { 305 return Collections.unmodifiableSet(specializes); 306 } 307 308 /** 309 * Add the specified interface description to the set of interfaces this interface 310 * description specializes. Return <code>true</code> if the set of interfaces this 311 * interface description specializes changed as a result of this call. 312 * 313 * @param specializes interface description to add, must not be null 314 * @return <code>true</code> if the set of interfaces this interface description specializes 315 * changed as a result of this call 316 */ 317 public boolean addSpecializes(final InterfaceDescription specializes) 318 { 319 if (specializes == null) 320 { 321 throw new IllegalArgumentException("specializes must not be null"); 322 } 323 if (this.specializes.contains(specializes)) 324 { 325 return false; 326 } 327 boolean rv = this.specializes.add(specializes); 328 329 if (rv) 330 { 331 for (Attribute a : specializes.getAttributes()) 332 { 333 addAttribute(a); 334 } 335 for (Association a : specializes.getAssociations()) 336 { 337 addAssociation(a); 338 } 339 } 340 return rv; 341 } 342 343 /** 344 * Add the specified interface description to the set of interfaces this interface 345 * description specializes. Return <code>true</code> if the set of interfaces this 346 * interface description specializes changed as a result of this call. 347 * 348 * @param specializes interface description to add, must not be null 349 * @return <code>true</code> if the set of interfaces this interface description specializes 350 * changed as a result of this call 351 */ 352 public boolean specializes(final InterfaceDescription specializes) 353 { 354 return addSpecializes(specializes); 355 } 356 357 /** 358 * Return an unmodifiable set of attributes for this interface description. 359 * 360 * @return an unmodifiable set of attributes for this interface description 361 */ 362 public Set<Attribute> getAttributes() 363 { 364 return Collections.unmodifiableSet(attributes); 365 } 366 367 /** 368 * Add the specified attribute to the set of attributes 369 * for this interface description. Return <code>true</code> if the set 370 * of attributes changed as a result of this call. 371 * 372 * @param attribute attribute to add, must not be null 373 * @return <code>true</code> if the set of attributes 374 * changed as a result of this call 375 */ 376 public boolean addAttribute(final Attribute attribute) 377 { 378 if (attribute == null) 379 { 380 throw new IllegalArgumentException("attribute must not be null"); 381 } 382 return attributes.add(attribute); 383 } 384 385 /** 386 * Add the specified attribute to the set of attributes 387 * for this interface description. Return <code>true</code> if the set 388 * of attributes changed as a result of this call. 389 * 390 * @param attribute attribute to add, must not be null 391 * @return <code>true</code> if the set of attributes 392 * changed as a result of this call 393 */ 394 public boolean attribute(final Attribute attribute) 395 { 396 return addAttribute(attribute); 397 } 398 399 /** 400 * Add a new attribute to the set of attributes for this 401 * interface description with the specified name, role name, 402 * and cardinality. The cardinality must be one of <b>Cardinality.ZeroToOne</b> 403 * or <b>Cardinality.StrictlyOne</b>. Return <code>true</code> if 404 * the set of attributes changed as a result of this call. 405 * 406 * @param name attribute name 407 * @param roleName role name 408 * @param cardinality cardinality, must not be null and must be 409 * one of <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b> 410 * @return <code>true</code> if the set of attributes 411 * changed as a result of this call 412 */ 413 public boolean attribute(final String name, final String roleName, final Cardinality cardinality) 414 { 415 Attribute a = new Attribute(name, roleName, cardinality); 416 return addAttribute(a); 417 } 418 419 /** 420 * Add a new attribute to the set of attributes for this 421 * interface description with the specified parameters. 422 * Return <code>true</code> if the set of attributes changed as 423 * a result of this call. 424 * 425 * @param name attribute name 426 * @param roleName role name 427 * @param cardinality cardinality, must not be null 428 * @param indexed true if the collection should be indexed 429 * @param unique true if the collection should not allow duplicate elements 430 * @param ordered true if the collection should iterate over elements in <i>insertion-order</i> 431 * @param sorted true if the collection should iterate over elements in ascending element order, 432 * sorted according to the <i>natural ordering</i> of its elements (see Comparable), or by a Comparator 433 * provided at creation time 434 * @return <code>true</code> if the set of attributes 435 * changed as a result of this call 436 */ 437 public boolean attribute(final String name, final String roleName, final Cardinality cardinality, 438 final boolean indexed, final boolean unique, final boolean ordered, final boolean sorted) 439 { 440 Attribute a = new Attribute(name, roleName, cardinality, indexed, unique, ordered, sorted); 441 return addAttribute(a); 442 } 443 444 /** 445 * Return an unmodifiable set of associations for this interface description. 446 * 447 * @return an unmodifiable set of associations for this interface description 448 */ 449 public Set<Association> getAssociations() 450 { 451 return Collections.unmodifiableSet(associations); 452 } 453 454 /** 455 * Add the specified association to the set of associations 456 * for this interface description. Return <code>true</code> if the set 457 * of associations changed as a result of this call. 458 * 459 * @param association association to add, must not be null 460 * @return <code>true</code> if the set of associations 461 * changed as a result of this call 462 */ 463 public boolean addAssociation(final Association association) 464 { 465 if (association == null) 466 { 467 throw new IllegalArgumentException("association must not be null"); 468 } 469 return associations.add(association); 470 } 471 472 /** 473 * Add the specified association to the set of associations 474 * for this interface description. Return <code>true</code> if the set 475 * of associations changed as a result of this call. 476 * 477 * @param association association to add, must not be null 478 * @return <code>true</code> if the set of associations 479 * changed as a result of this call 480 */ 481 public boolean associate(final Association association) 482 { 483 return addAssociation(association); 484 } 485 486 /** 487 * Add a new association to the set of associations for this 488 * interface description to the specified class with the 489 * specified cardinality. The assocation's role name will be 490 * the same as the class' name. The cardinality must be one of 491 * <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b>. 492 * Return <code>true</code> if the set of associations changed as a result of 493 * this call. 494 * 495 * @param cd class description, must not be null 496 * @param cardinality cardinality, must not be null and must be 497 * one of <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b> 498 * @return <code>true</code> if the set of associations 499 * changed as a result of this call 500 */ 501 public boolean associate(final ClassDescription cd, final Cardinality cardinality) 502 { 503 Association a = new Association(cd, cd.getUpper(), cardinality); 504 return addAssociation(a); 505 } 506 507 /** 508 * Add a new association to the set of attributes for this 509 * interface description to the specified class with the 510 * specified role name and cardinality. The cardinality must be one of 511 * <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b>. 512 * Return <code>true</code> if the set of associations changed as a result of 513 * this call. 514 * 515 * @param cd class description, must not be null 516 * @param roleName role name 517 * @param cardinality cardinality, must not be null and must be 518 * one of <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b> 519 * @return <code>true</code> if the set of associations 520 * changed as a result of this call 521 */ 522 public boolean associate(final ClassDescription cd, final String roleName, final Cardinality cardinality) 523 { 524 Association a = new Association(cd, roleName, cardinality); 525 return addAssociation(a); 526 } 527 528 /** 529 * Add a new association to the set of associations for this 530 * interface description to the specified class with the specified 531 * parameters. The association's role name will be the same as 532 * the class' name. 533 * 534 * @param cd class description, must not be null 535 * @param cardinality cardinality, must not be null 536 * @param indexed true if the collection should be indexed 537 * @param unique true if the collection should not allow duplicate elements 538 * @param ordered true if the collection should iterate over elements in <i>insertion-order</i> 539 * @param sorted true if the collection should iterate over elements in ascending element order, 540 * sorted according to the <i>natural ordering</i> of its elements (see Comparable), or by a Comparator 541 * provided at creation time 542 * @return <code>true</code> if the set of associations 543 * changed as a result of this call 544 */ 545 public boolean associate(final ClassDescription cd, final Cardinality cardinality, 546 final boolean indexed, final boolean unique, final boolean ordered, final boolean sorted) 547 { 548 Association a = new Association(cd, cd.getUpper(), cardinality, indexed, unique, ordered, sorted); 549 return addAssociation(a); 550 } 551 552 /** 553 * Add a new association to the set of associations for this 554 * interface description to the specified class with the specified 555 * parameters. 556 * 557 * @param cd class description, must not be null 558 * @param roleName role name 559 * @param cardinality cardinality, must not be null 560 * @param indexed true if the collection should be indexed 561 * @param unique true if the collection should not allow duplicate elements 562 * @param ordered true if the collection should iterate over elements in <i>insertion-order</i> 563 * @param sorted true if the collection should iterate over elements in ascending element order, 564 * sorted according to the <i>natural ordering</i> of its elements (see Comparable), or by a Comparator 565 * provided at creation time 566 * @return <code>true</code> if the set of associations 567 * changed as a result of this call 568 */ 569 public boolean associate(final ClassDescription cd, final String roleName, final Cardinality cardinality, 570 final boolean indexed, final boolean unique, final boolean ordered, final boolean sorted) 571 { 572 Association a = new Association(cd, roleName, cardinality, indexed, unique, ordered, sorted); 573 return addAssociation(a); 574 } 575 576 /** 577 * Add a new association to the set of associations for this 578 * interface description to the specified interface with the 579 * specified cardinality. The assocation's role name will be 580 * the same as the interface's name. The cardinality must be one of 581 * <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b>. 582 * Return <code>true</code> if the set of associations changed as a result of 583 * this call. 584 * 585 * @param id interface description, must not be null 586 * @param cardinality cardinality, must not be null and must be 587 * one of <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b> 588 * @return <code>true</code> if the set of associations 589 * changed as a result of this call 590 */ 591 public boolean associate(final InterfaceDescription id, final Cardinality cardinality) 592 { 593 Association a = new Association(id, id.getUpper(), cardinality); 594 return addAssociation(a); 595 } 596 597 598 /** 599 * Add a new association to the set of attributes for this 600 * interface description to the specified interface with the 601 * specified role name and cardinality. The cardinality must be one of 602 * <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b>. 603 * Return <code>true</code> if the set of associations changed as a result of 604 * this call. 605 * 606 * @param id interface description, must not be null 607 * @param roleName role name 608 * @param cardinality cardinality, must not be null and must be 609 * one of <b>Cardinality.ZeroToOne</b> or <b>Cardinality.StrictlyOne</b> 610 * @return <code>true</code> if the set of associations 611 * changed as a result of this call 612 */ 613 public boolean associate(final InterfaceDescription id, final String roleName, final Cardinality cardinality) 614 { 615 Association a = new Association(id, roleName, cardinality); 616 return addAssociation(a); 617 } 618 619 /** 620 * Add a new association to the set of associations for this 621 * interface description to the specified interface with the specified 622 * parameters. The association's role name will be the same as 623 * the interface's name. 624 * 625 * @param id interface description, must not be null 626 * @param cardinality cardinality, must not be null 627 * @param indexed true if the collection should be indexed 628 * @param unique true if the collection should not allow duplicate elements 629 * @param ordered true if the collection should iterate over elements in <i>insertion-order</i> 630 * @param sorted true if the collection should iterate over elements in ascending element order, 631 * sorted according to the <i>natural ordering</i> of its elements (see Comparable), or by a Comparator 632 * provided at creation time 633 * @return <code>true</code> if the set of associations 634 * changed as a result of this call 635 */ 636 public boolean associate(final InterfaceDescription id, final Cardinality cardinality, 637 final boolean indexed, final boolean unique, final boolean ordered, final boolean sorted) 638 { 639 Association a = new Association(id, id.getUpper(), cardinality, indexed, unique, ordered, sorted); 640 return addAssociation(a); 641 } 642 643 /** 644 * Add a new association to the set of associations for this 645 * interface description to the specified interface with the specified 646 * parameters. 647 * 648 * @param id interface description, must not be null 649 * @param roleName role name 650 * @param cardinality cardinality, must not be null 651 * @param indexed true if the collection should be indexed 652 * @param unique true if the collection should not allow duplicate elements 653 * @param ordered true if the collection should iterate over elements in <i>insertion-order</i> 654 * @param sorted true if the collection should iterate over elements in ascending element order, 655 * sorted according to the <i>natural ordering</i> of its elements (see Comparable), or by a Comparator 656 * provided at creation time 657 * @return <code>true</code> if the set of associations 658 * changed as a result of this call 659 */ 660 public boolean associate(final InterfaceDescription id, final String roleName, final Cardinality cardinality, 661 final boolean indexed, final boolean unique, final boolean ordered, final boolean sorted) 662 { 663 Association a = new Association(id, roleName, cardinality, indexed, unique, ordered, sorted); 664 return addAssociation(a); 665 } 666 }