Introduction

The Class Diagram is one of thirteen diagrams of the Unified Modeling Language (UML). It is the diagram used to depict the classes (or entities) in a system or domain. UML Class Diagrams are a common visual notation for ontologies and conceptual data/information models.

This short lesson explains how to specify the correct multiplicities between classes in a UML Class Diagram by viewing them as mapping between sets of objects. Multiplicities are a type of domain constraint and they express business rules.

While there are several different kinds of relationships in UML Class Diagrams, multiplicity constraints only apply to association, aggregation, and composition. Most notably, they are not specified for generalization.

So, the ensuing discussion only applies to association, aggregation, and composition as those are relationships between instances of classes (objects) rather than a static relationship between classes.


The diagrams presented in this tutorial were drawn using LucidChart and can be accessed at this link.


Review of Class Diagrams

In class diagrams, information architects define:

  • Classes (a concept, things, object, role, event, person; equivalent of entity in an ERD in database design)
  • Attributes of a class representing property along with the data type and possible default value
  • Methods (or operations) representing its behavior

In UML, a class is represented with a three-compartment rounded-corner box, as shown below. In class diagrams depicting an ontology (or conceptual model), the third compartment sometimes contains a definition rather than methods. The attribute that uniquely identifies each instance is often tagged using the UML stereotype «key».

An abstract class (one which exist solely to organize a class hierarchy and is not instantiable) is indicated visually with either the stereotype «abstract» or by italicizing the class name. The example diagram below illustrates the two styles. To be meaningful, abstract classes must have at least two subclasses.

Review of Relationship Types

Relationships which are grouped into two categories:

  • Relationships between objects (instances of classes) differentiated into Dependency, Association, Aggregation and Composition

  • Relationships between classes of two kinds in terms of Generalization/Inheritance and Realization/Implementation

Relationships are always bi-directional. It is equally valid to say that A is linked to B as it is to say that B is linked to A.

Aggregation and composition are special types of associations, which means that all properties of an association (such as having a label and multiplicities) apply, by definition, to aggregation and composition. Further, composition is a special kind of aggregation.

The UML meta-model below shows the relationships between “relationships”:

Association

An association is a simple semantic relationship between two classes that indicates a link between them. For example, “a portfolio is owned by an investor” is an example of an association. The two classes are linked but neither is part of the other or a kind of the other. As the association is bi-directional, it can be inverted, so it is equally valid to say that “An investor owns a portfolio”. The actual phrase is generally found through domain analysis.

Multiplicity Constraints

The multiplicity bounds are generally as text string in the format:

<lower-bound> ‘..’ <upper-bound>

where <lower-bound> is an integer and <upper-bound> is a of type unlimited natural with the restriction that <lower-bound> ≤ <upper-bound>.

If the multiplicity is associated with a multiplicity whose notation is a text string (such as an attribute), the multiplicity string is placed within square brackets ([ ]) as part of that text string.

Unbounded Upper Bound with *

The star character (*) is used as part of a multiplicity specification to represent an unlimited upper bound.

While a multiplicity constraint of “*” is valid and implies a lower bound of 0, it is recommended to specify a lower bound explicitly (e.g., 0..* or 1..*) as the implied lower bound of “0” may not be known to the reader of a UML Class Diagram.

Equal Upper and Lower Bounds

If the lower bound is equal to the upper bound, then an alternate notation is to use a string containing just the upper bound. For example, “1” is semantically equivalent to “1..1” multiplicity. A multiplicity with zero as the lower bound and an unspecified upper bound may use the alternative notation containing a single star “*” instead of “0..*” multiplicity.

The specific notation for the ordering and uniqueness specifications may vary depending on the specific kind of multiplicity element. A general notation is to use a textual annotation containing “ordered” or “unordered” to define the ordering, and “unique” or “non-unique” to define the uniqueness.

Examples of Multiplicity Definitions

Example Multiplicity Semantics
0..1 no more than one, but possibly none
1..10 at least one but no more than 10
0..* no specific upper bound and possibly none
5..* at least five, but no upper limit
1..1 exactly 1; same as 1
10 exactly 10; same as 10..10
1..[C.n] at least one but no more than the value of the (integer) attribute n in the class or object \(C\)

Label Direction vs Navigation Direction

An association is represented as a line (without arrows) between two classes. The classes are often referred to as the source and the target. A verb-phrase label is often added to assist in understanding the nature of the relationship along with an arrow (▶) indicating the reading direction of the label. The label is optional. The example below depicts the association between an investor and a portfolio in an finance or investment domain.

A few notes to keep in mind:

  • the line should not have an arrow at one end
  • an arrow as part of the label indicates the reading direction of the verb-phrase and does not indicate any kind of direction for the association

Interpreting Multiplicities

In the diagram below, the relationship between classes “Auction” and “Bid” should be read as follows:

  1. Any (one) bid is made in exactly one auction.
  2. Any (one) auction has multiple bids made in it; there is no limit on the bids and some auctions may not have any bids.

We can think of classes as sets of instances (objects), which means that an association relationship is a mapping between objects of one set to objects of another set.

For example, auction 7467 does not have any bids, while auction 8613 has two bids (bids 101 and 102). Every bid is connected to from exactly one auction; there are no bids that are not connected to an auction.

Conclusion

Relationships between object instances (association, aggregation, and composition) must have multiplicities that define the mapping between the class instances of the respective classes.

Tutorial

The video tutorial below explains in more detail the concept of a relationship between objects as a mapping between two sets, or a function that maps an instance of class A to zero or more instances of class B.


Files & Resources

All Files for Lesson 30.153

References

None.

Errata

Let us know.

LS0tCnRpdGxlOiAiU3BlY2lmeWluZyBhbmQgSW50ZXJwcmV0aW5nIE11bHRpcGxpY2l0eSBpbiBVTUwiCnBhcmFtczoKICB0eXBlOiBsZXNzb24KICBjYXRlZ29yeTogMzAKICBzdGFja3M6ICIwLDAiCiAgbnVtYmVyOiAxNTMKICB0aW1lOiAzMAogIGxldmVsOiBiZWdpbm5lcgogIHRhZ3M6IFVNTCxNdWx0aXBsaWNpdHksQ2xhc3MgRGlhZ3JhbQogIGRlc2NyaXB0aW9uOiAiVGhpcyBsZXNzb24gZXhwbGFpbnMgd2hhdCBtdWx0aXBsaWNpdHkgY29uc3RyYWludHMgbWVhbiBpbiBVTUwKICAgICAgICAgICAgICAgIGFuZCBob3cgdG8gcHJvcGVybHkgZGVmaW5lcyBhbmQgaW50ZXJwcmV0IHRoZW0gdXNpbmcgY2xhc3NlcwogICAgICAgICAgICAgICAgYXMgc2V0cyBvZiBvYmplY3RzLiIKZGF0ZTogIjxzbWFsbD5gciBTeXMuRGF0ZSgpYDwvc21hbGw+IgphdXRob3I6ICI8c21hbGw+TWFydGluIFNjaGVkbGJhdWVyPC9zbWFsbD4iCmVtYWlsOiAibS5zY2hlZGxiYXVlckBuZXUuZWR1IgphZmZpbGl0YXRpb246ICJOb3J0aGVhc3Rlcm4gVW5pdmVyc2l0eSIKb3V0cHV0OiAKICBib29rZG93bjo6aHRtbF9kb2N1bWVudDI6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgY29sbGFwc2VkOiBmYWxzZQogICAgbnVtYmVyX3NlY3Rpb25zOiBmYWxzZQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IHNwYWNlbGFiCiAgICBoaWdobGlnaHQ6IHRhbmdvCi0tLQoKLS0tCnRpdGxlOiAiPHNtYWxsPmByIHBhcmFtcyRjYXRlZ29yeWAuYHIgcGFyYW1zJG51bWJlcmA8L3NtYWxsPjxici8+PHNwYW4gc3R5bGU9J2NvbG9yOiAjMkU0MDUzOyBmb250LXNpemU6IDAuOWVtJz5gciBybWFya2Rvd246Om1ldGFkYXRhJHRpdGxlYDwvc3Bhbj4iCi0tLQoKYGBge3IgY29kZT14ZnVuOjpyZWFkX3V0ZjgocGFzdGUwKGhlcmU6OmhlcmUoKSwnL1IvX2luc2VydDJEQi5SJykpLCBpbmNsdWRlID0gRkFMU0V9CmBgYAoKIyMgSW50cm9kdWN0aW9uCgpUaGUgKkNsYXNzIERpYWdyYW0qIGlzIG9uZSBvZiB0aGlydGVlbiBkaWFncmFtcyBvZiB0aGUgW1VuaWZpZWQgTW9kZWxpbmcgTGFuZ3VhZ2UgKFVNTCldKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1VuaWZpZWRfTW9kZWxpbmdfTGFuZ3VhZ2UpLiBJdCBpcyB0aGUgZGlhZ3JhbSB1c2VkIHRvIGRlcGljdCB0aGUgY2xhc3NlcyAob3IgZW50aXRpZXMpIGluIGEgc3lzdGVtIG9yIGRvbWFpbi4gVU1MIENsYXNzIERpYWdyYW1zIGFyZSBhIGNvbW1vbiB2aXN1YWwgbm90YXRpb24gZm9yIG9udG9sb2dpZXMgYW5kIGNvbmNlcHR1YWwgZGF0YS9pbmZvcm1hdGlvbiBtb2RlbHMuCgpUaGlzIHNob3J0IGxlc3NvbiBleHBsYWlucyBob3cgdG8gc3BlY2lmeSB0aGUgY29ycmVjdCBtdWx0aXBsaWNpdGllcyBiZXR3ZWVuIGNsYXNzZXMgaW4gYSBVTUwgQ2xhc3MgRGlhZ3JhbSBieSB2aWV3aW5nIHRoZW0gYXMgbWFwcGluZyBiZXR3ZWVuIHNldHMgb2Ygb2JqZWN0cy4gTXVsdGlwbGljaXRpZXMgYXJlIGEgdHlwZSBvZiBkb21haW4gY29uc3RyYWludCBhbmQgdGhleSBleHByZXNzIGJ1c2luZXNzIHJ1bGVzLgoKPiBXaGlsZSB0aGVyZSBhcmUgc2V2ZXJhbCBkaWZmZXJlbnQga2luZHMgb2YgcmVsYXRpb25zaGlwcyBpbiBVTUwgQ2xhc3MgRGlhZ3JhbXMsIG11bHRpcGxpY2l0eSBjb25zdHJhaW50cyBvbmx5IGFwcGx5IHRvIGFzc29jaWF0aW9uLCBhZ2dyZWdhdGlvbiwgYW5kIGNvbXBvc2l0aW9uLiBNb3N0IG5vdGFibHksIHRoZXkgYXJlIG5vdCBzcGVjaWZpZWQgZm9yIGdlbmVyYWxpemF0aW9uLgoKU28sIHRoZSBlbnN1aW5nIGRpc2N1c3Npb24gb25seSBhcHBsaWVzIHRvIGFzc29jaWF0aW9uLCBhZ2dyZWdhdGlvbiwgYW5kIGNvbXBvc2l0aW9uIGFzIHRob3NlIGFyZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gaW5zdGFuY2VzIG9mIGNsYXNzZXMgKG9iamVjdHMpIHJhdGhlciB0aGFuIGEgc3RhdGljIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGNsYXNzZXMuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClRoZSBkaWFncmFtcyBwcmVzZW50ZWQgaW4gdGhpcyB0dXRvcmlhbCB3ZXJlIGRyYXduIHVzaW5nIFtMdWNpZENoYXJ0XShodHRwczovL2x1Y2lkLmFwcCkgYW5kIGNhbiBiZSBhY2Nlc3NlZCBhdCB0aGlzIFtsaW5rXShodHRwczovL2x1Y2lkLmFwcC9sdWNpZGNoYXJ0L2ZlYWEyNzNmLTkzYWUtNDRkOS1iOGMwLTUxY2UzMmEyYjQwYi9lZGl0P2ludml0YXRpb25JZD1pbnZfYmYxNzExOGYtOTAzYS00NmU1LWE2YjAtOWJjYjVmNjZjYWEzKS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIFJldmlldyBvZiBDbGFzcyBEaWFncmFtcwoKSW4gY2xhc3MgZGlhZ3JhbXMsIGluZm9ybWF0aW9uIGFyY2hpdGVjdHMgZGVmaW5lOgoKLSAgIENsYXNzZXMgKGEgY29uY2VwdCwgdGhpbmdzLCBvYmplY3QsIHJvbGUsIGV2ZW50LCBwZXJzb247IGVxdWl2YWxlbnQgb2YgZW50aXR5IGluIGFuIEVSRCBpbiBkYXRhYmFzZSBkZXNpZ24pCi0gICBBdHRyaWJ1dGVzIG9mIGEgY2xhc3MgcmVwcmVzZW50aW5nIHByb3BlcnR5IGFsb25nIHdpdGggdGhlIGRhdGEgdHlwZSBhbmQgcG9zc2libGUgZGVmYXVsdCB2YWx1ZQotICAgTWV0aG9kcyAob3Igb3BlcmF0aW9ucykgcmVwcmVzZW50aW5nIGl0cyBiZWhhdmlvcgoKSW4gVU1MLCBhIGNsYXNzIGlzIHJlcHJlc2VudGVkIHdpdGggYSB0aHJlZS1jb21wYXJ0bWVudCByb3VuZGVkLWNvcm5lciBib3gsIGFzIHNob3duIGJlbG93LiBJbiBjbGFzcyBkaWFncmFtcyBkZXBpY3RpbmcgYW4gb250b2xvZ3kgKG9yIGNvbmNlcHR1YWwgbW9kZWwpLCB0aGUgdGhpcmQgY29tcGFydG1lbnQgc29tZXRpbWVzIGNvbnRhaW5zIGEgZGVmaW5pdGlvbiByYXRoZXIgdGhhbiBtZXRob2RzLiBUaGUgYXR0cmlidXRlIHRoYXQgdW5pcXVlbHkgaWRlbnRpZmllcyBlYWNoIGluc3RhbmNlIGlzIG9mdGVuIHRhZ2dlZCB1c2luZyB0aGUgVU1MIHN0ZXJlb3R5cGUgKsKra2V5wrsqLgoKQW4gYWJzdHJhY3QgY2xhc3MgKG9uZSB3aGljaCBleGlzdCBzb2xlbHkgdG8gb3JnYW5pemUgYSBjbGFzcyBoaWVyYXJjaHkgYW5kIGlzIG5vdCBpbnN0YW50aWFibGUpIGlzIGluZGljYXRlZCB2aXN1YWxseSB3aXRoIGVpdGhlciB0aGUgc3RlcmVvdHlwZSAqwqthYnN0cmFjdMK7KiBvciBieSBpdGFsaWNpemluZyB0aGUgY2xhc3MgbmFtZS4gVGhlIGV4YW1wbGUgZGlhZ3JhbSBiZWxvdyBpbGx1c3RyYXRlcyB0aGUgdHdvIHN0eWxlcy4gVG8gYmUgbWVhbmluZ2Z1bCwgYWJzdHJhY3QgY2xhc3NlcyBtdXN0IGhhdmUgYXQgbGVhc3QgdHdvIHN1YmNsYXNzZXMuCgojIyBSZXZpZXcgb2YgUmVsYXRpb25zaGlwIFR5cGVzCgpSZWxhdGlvbnNoaXBzIHdoaWNoIGFyZSBncm91cGVkIGludG8gdHdvIGNhdGVnb3JpZXM6CgotICAgUmVsYXRpb25zaGlwcyBiZXR3ZWVuIG9iamVjdHMgKGluc3RhbmNlcyBvZiBjbGFzc2VzKSBkaWZmZXJlbnRpYXRlZCBpbnRvIERlcGVuZGVuY3ksIEFzc29jaWF0aW9uLCBBZ2dyZWdhdGlvbiBhbmQgQ29tcG9zaXRpb24KCi0gICBSZWxhdGlvbnNoaXBzIGJldHdlZW4gY2xhc3NlcyBvZiB0d28ga2luZHMgaW4gdGVybXMgb2YgR2VuZXJhbGl6YXRpb24vSW5oZXJpdGFuY2UgYW5kIFJlYWxpemF0aW9uL0ltcGxlbWVudGF0aW9uCgpSZWxhdGlvbnNoaXBzIGFyZSBhbHdheXMgKmJpLWRpcmVjdGlvbmFsKi4gSXQgaXMgZXF1YWxseSB2YWxpZCB0byBzYXkgdGhhdCAqQSogaXMgbGlua2VkIHRvICpCKiBhcyBpdCBpcyB0byBzYXkgdGhhdCAqQiogaXMgbGlua2VkIHRvICpBKi4KCkFnZ3JlZ2F0aW9uIGFuZCBjb21wb3NpdGlvbiBhcmUgc3BlY2lhbCB0eXBlcyBvZiBhc3NvY2lhdGlvbnMsIHdoaWNoIG1lYW5zIHRoYXQgYWxsIHByb3BlcnRpZXMgb2YgYW4gYXNzb2NpYXRpb24gKHN1Y2ggYXMgaGF2aW5nIGEgbGFiZWwgYW5kIG11bHRpcGxpY2l0aWVzKSBhcHBseSwgYnkgZGVmaW5pdGlvbiwgdG8gYWdncmVnYXRpb24gYW5kIGNvbXBvc2l0aW9uLiBGdXJ0aGVyLCBjb21wb3NpdGlvbiBpcyBhIHNwZWNpYWwga2luZCBvZiBhZ2dyZWdhdGlvbi4KClRoZSBVTUwgbWV0YS1tb2RlbCBiZWxvdyBzaG93cyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuICJyZWxhdGlvbnNoaXBzIjoKCiFbXShodHRwczovL3MzLnVzLWVhc3QtMi5hbWF6b25hd3MuY29tL2FydGlmaWNpdW0udXMvbGVzc29ucy8zMC52aXNtb2RlbGluZy9sLTMwLTE1NS11bWwtcmVsYXRpb25zaGlwcy9pbWFnZXMvbC0zMC0xNTUtdW1sLW1ldGEtbW9kZWwuanBnKQoKIyMjIEFzc29jaWF0aW9uCgpBbiBhc3NvY2lhdGlvbiBpcyBhIHNpbXBsZSBzZW1hbnRpYyByZWxhdGlvbnNoaXAgYmV0d2VlbiB0d28gY2xhc3NlcyB0aGF0IGluZGljYXRlcyBhIGxpbmsgYmV0d2VlbiB0aGVtLiBGb3IgZXhhbXBsZSwgKiJhIHBvcnRmb2xpbyBpcyBvd25lZCBieSBhbiBpbnZlc3RvciIqIGlzIGFuIGV4YW1wbGUgb2YgYW4gYXNzb2NpYXRpb24uIFRoZSB0d28gY2xhc3NlcyBhcmUgbGlua2VkIGJ1dCBuZWl0aGVyIGlzIHBhcnQgb2YgdGhlIG90aGVyIG9yIGEga2luZCBvZiB0aGUgb3RoZXIuIEFzIHRoZSBhc3NvY2lhdGlvbiBpcyBiaS1kaXJlY3Rpb25hbCwgaXQgY2FuIGJlIGludmVydGVkLCBzbyBpdCBpcyBlcXVhbGx5IHZhbGlkIHRvIHNheSB0aGF0ICoiQW4gaW52ZXN0b3Igb3ducyBhIHBvcnRmb2xpbyIqLiBUaGUgYWN0dWFsIHBocmFzZSBpcyBnZW5lcmFsbHkgZm91bmQgdGhyb3VnaCBkb21haW4gYW5hbHlzaXMuCgohW10oaW1hZ2VzL0ludlBvcnRBc3NvY0xibE5vTXVsdC5qcGcpe3dpZHRoPSI3MCUifQoKIyMgTXVsdGlwbGljaXR5IENvbnN0cmFpbnRzCgpUaGUgbXVsdGlwbGljaXR5IGJvdW5kcyBhcmUgZ2VuZXJhbGx5IGFzIHRleHQgc3RyaW5nIGluIHRoZSBmb3JtYXQ6Cgo8Y29kZT5cPGxvd2VyLWJvdW5kXD4gJy4uJyBcPHVwcGVyLWJvdW5kXD48L2NvZGU+Cgp3aGVyZSAqXDxsb3dlci1ib3VuZFw+KiBpcyBhbiBpbnRlZ2VyIGFuZCAqXDx1cHBlci1ib3VuZFw+KiBpcyBhIG9mIHR5cGUgdW5saW1pdGVkIG5hdHVyYWwgd2l0aCB0aGUgcmVzdHJpY3Rpb24gdGhhdCAqXDxsb3dlci1ib3VuZFw+IOKJpCBcPHVwcGVyLWJvdW5kXD4qLgoKSWYgdGhlIG11bHRpcGxpY2l0eSBpcyBhc3NvY2lhdGVkIHdpdGggYSBtdWx0aXBsaWNpdHkgd2hvc2Ugbm90YXRpb24gaXMgYSB0ZXh0IHN0cmluZyAoc3VjaCBhcyBhbiBhdHRyaWJ1dGUpLCB0aGUgbXVsdGlwbGljaXR5IHN0cmluZyBpcyBwbGFjZWQgd2l0aGluIHNxdWFyZSBicmFja2V0cyAoWyBdKSBhcyBwYXJ0IG9mIHRoYXQgdGV4dCBzdHJpbmcuCgojIyMgVW5ib3VuZGVkIFVwcGVyIEJvdW5kIHdpdGggXCoKClRoZSBzdGFyIGNoYXJhY3RlciAoXCopIGlzIHVzZWQgYXMgcGFydCBvZiBhIG11bHRpcGxpY2l0eSBzcGVjaWZpY2F0aW9uIHRvIHJlcHJlc2VudCBhbiB1bmxpbWl0ZWQgdXBwZXIgYm91bmQuCgpXaGlsZSBhIG11bHRpcGxpY2l0eSBjb25zdHJhaW50IG9mICJcKiIgaXMgdmFsaWQgYW5kIGltcGxpZXMgYSBsb3dlciBib3VuZCBvZiAqMCosIGl0IGlzIHJlY29tbWVuZGVkIHRvIHNwZWNpZnkgYSBsb3dlciBib3VuZCBleHBsaWNpdGx5ICgqZS5nLiosICowLi5cKiogb3IgKjEuLlwqKikgYXMgdGhlIGltcGxpZWQgbG93ZXIgYm91bmQgb2YgIjAiIG1heSBub3QgYmUga25vd24gdG8gdGhlIHJlYWRlciBvZiBhIFVNTCBDbGFzcyBEaWFncmFtLgoKIyMjIEVxdWFsIFVwcGVyIGFuZCBMb3dlciBCb3VuZHMKCklmIHRoZSBsb3dlciBib3VuZCBpcyBlcXVhbCB0byB0aGUgdXBwZXIgYm91bmQsIHRoZW4gYW4gYWx0ZXJuYXRlIG5vdGF0aW9uIGlzIHRvIHVzZSBhIHN0cmluZyBjb250YWluaW5nIGp1c3QgdGhlIHVwcGVyIGJvdW5kLiBGb3IgZXhhbXBsZSwgIjEiIGlzIHNlbWFudGljYWxseSBlcXVpdmFsZW50IHRvICoiMS4uMSIqIG11bHRpcGxpY2l0eS4gQSBtdWx0aXBsaWNpdHkgd2l0aCB6ZXJvIGFzIHRoZSBsb3dlciBib3VuZCBhbmQgYW4gdW5zcGVjaWZpZWQgdXBwZXIgYm91bmQgbWF5IHVzZSB0aGUgYWx0ZXJuYXRpdmUgbm90YXRpb24gY29udGFpbmluZyBhIHNpbmdsZSBzdGFyICJcKiIgaW5zdGVhZCBvZiAqIjAuLlwqIiogbXVsdGlwbGljaXR5LgoKVGhlIHNwZWNpZmljIG5vdGF0aW9uIGZvciB0aGUgb3JkZXJpbmcgYW5kIHVuaXF1ZW5lc3Mgc3BlY2lmaWNhdGlvbnMgbWF5IHZhcnkgZGVwZW5kaW5nIG9uIHRoZSBzcGVjaWZpYyBraW5kIG9mIG11bHRpcGxpY2l0eSBlbGVtZW50LiBBIGdlbmVyYWwgbm90YXRpb24gaXMgdG8gdXNlIGEgdGV4dHVhbCBhbm5vdGF0aW9uIGNvbnRhaW5pbmcgIm9yZGVyZWQiIG9yICJ1bm9yZGVyZWQiIHRvIGRlZmluZSB0aGUgb3JkZXJpbmcsIGFuZCAidW5pcXVlIiBvciAibm9uLXVuaXF1ZSIgdG8gZGVmaW5lIHRoZSB1bmlxdWVuZXNzLgoKIyMjIEV4YW1wbGVzIG9mIE11bHRpcGxpY2l0eSBEZWZpbml0aW9ucwoKfCBFeGFtcGxlIE11bHRpcGxpY2l0eSB8IFNlbWFudGljcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8Oi0tLS0tLS0tLS0tLS0tLS0tLS0tOnw6LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS18CnwgICAgICAgICAwLi4xICAgICAgICAgfCBubyBtb3JlIHRoYW4gb25lLCBidXQgcG9zc2libHkgbm9uZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCAgICAgICAgMS4uMTAgICAgICAgICB8IGF0IGxlYXN0IG9uZSBidXQgbm8gbW9yZSB0aGFuIDEwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8ICAgICAgICAwLi5cKiAgICAgICAgIHwgbm8gc3BlY2lmaWMgdXBwZXIgYm91bmQgYW5kIHBvc3NpYmx5IG5vbmUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgIDUuLlwqICAgICAgICAgfCBhdCBsZWFzdCBmaXZlLCBidXQgbm8gdXBwZXIgbGltaXQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCAgICAgICAgIDEuLjEgICAgICAgICB8IGV4YWN0bHkgMTsgc2FtZSBhcyAxICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfAp8ICAgICAgICAgIDEwICAgICAgICAgIHwgZXhhY3RseSAxMDsgc2FtZSBhcyAxMC4uMTAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8CnwgICAgICAgMS4uW0Mubl0gICAgICAgfCBhdCBsZWFzdCBvbmUgYnV0IG5vIG1vcmUgdGhhbiB0aGUgdmFsdWUgb2YgdGhlIChpbnRlZ2VyKSBhdHRyaWJ1dGUgKm4qIGluIHRoZSBjbGFzcyBvciBvYmplY3QgJEMkIHwKCiMjIExhYmVsIERpcmVjdGlvbiB2cyBOYXZpZ2F0aW9uIERpcmVjdGlvbgoKQW4gYXNzb2NpYXRpb24gaXMgcmVwcmVzZW50ZWQgYXMgYSBsaW5lICh3aXRob3V0IGFycm93cykgYmV0d2VlbiB0d28gY2xhc3Nlcy4gVGhlIGNsYXNzZXMgYXJlIG9mdGVuIHJlZmVycmVkIHRvIGFzIHRoZSBzb3VyY2UgYW5kIHRoZSB0YXJnZXQuIEEgdmVyYi1waHJhc2UgbGFiZWwgaXMgb2Z0ZW4gYWRkZWQgdG8gYXNzaXN0IGluIHVuZGVyc3RhbmRpbmcgdGhlIG5hdHVyZSBvZiB0aGUgcmVsYXRpb25zaGlwIGFsb25nIHdpdGggYW4gYXJyb3cgKOKWtikgaW5kaWNhdGluZyB0aGUgcmVhZGluZyBkaXJlY3Rpb24gb2YgdGhlIGxhYmVsLiBUaGUgbGFiZWwgaXMgb3B0aW9uYWwuIFRoZSBleGFtcGxlIGJlbG93IGRlcGljdHMgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gYW4gaW52ZXN0b3IgYW5kIGEgcG9ydGZvbGlvIGluIGFuIGZpbmFuY2Ugb3IgaW52ZXN0bWVudCBkb21haW4uCgohW10oaW1hZ2VzL05hdlJlYWREaXJVTUwuanBlZykKCkEgZmV3IG5vdGVzIHRvIGtlZXAgaW4gbWluZDoKCi0gICB0aGUgbGluZSBzaG91bGQgbm90IGhhdmUgYW4gYXJyb3cgYXQgb25lIGVuZAotICAgYW4gYXJyb3cgYXMgcGFydCBvZiB0aGUgbGFiZWwgaW5kaWNhdGVzIHRoZSByZWFkaW5nIGRpcmVjdGlvbiBvZiB0aGUgdmVyYi1waHJhc2UgYW5kIGRvZXMgbm90IGluZGljYXRlIGFueSBraW5kIG9mIGRpcmVjdGlvbiBmb3IgdGhlIGFzc29jaWF0aW9uCgojIyBJbnRlcnByZXRpbmcgTXVsdGlwbGljaXRpZXMKCkluIHRoZSBkaWFncmFtIGJlbG93LCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gY2xhc3NlcyAiQXVjdGlvbiIgYW5kICJCaWQiIHNob3VsZCBiZSByZWFkIGFzIGZvbGxvd3M6CgoxLiAgQW55IChvbmUpIGJpZCBpcyBtYWRlIGluIGV4YWN0bHkgb25lIGF1Y3Rpb24uCjIuICBBbnkgKG9uZSkgYXVjdGlvbiBoYXMgbXVsdGlwbGUgYmlkcyBtYWRlIGluIGl0OyB0aGVyZSBpcyBubyBsaW1pdCBvbiB0aGUgYmlkcyBhbmQgc29tZSBhdWN0aW9ucyBtYXkgbm90IGhhdmUgYW55IGJpZHMuCgohW10oaW1hZ2VzL2F1Y3Rpb24tYmlkLXVtbC5wbmcpe3dpZHRoPSI3MCUifQoKV2UgY2FuIHRoaW5rIG9mIGNsYXNzZXMgYXMgc2V0cyBvZiBpbnN0YW5jZXMgKG9iamVjdHMpLCB3aGljaCBtZWFucyB0aGF0IGFuIGFzc29jaWF0aW9uIHJlbGF0aW9uc2hpcCBpcyBhIG1hcHBpbmcgYmV0d2VlbiBvYmplY3RzIG9mIG9uZSBzZXQgdG8gb2JqZWN0cyBvZiBhbm90aGVyIHNldC4KCiFbXShpbWFnZXMvT2JqZWN0U2V0TWFwcGluZ3MuanBnKXt3aWR0aD0iNzAlIn0KCkZvciBleGFtcGxlLCBhdWN0aW9uIDc0NjcgZG9lcyBub3QgaGF2ZSBhbnkgYmlkcywgd2hpbGUgYXVjdGlvbiA4NjEzIGhhcyB0d28gYmlkcyAoYmlkcyAxMDEgYW5kIDEwMikuIEV2ZXJ5IGJpZCBpcyBjb25uZWN0ZWQgdG8gZnJvbSBleGFjdGx5IG9uZSBhdWN0aW9uOyB0aGVyZSBhcmUgbm8gYmlkcyB0aGF0IGFyZSBub3QgY29ubmVjdGVkIHRvIGFuIGF1Y3Rpb24uCgojIyBDb25jbHVzaW9uIHsjY29uY2x9CgpSZWxhdGlvbnNoaXBzIGJldHdlZW4gb2JqZWN0IGluc3RhbmNlcyAoYXNzb2NpYXRpb24sIGFnZ3JlZ2F0aW9uLCBhbmQgY29tcG9zaXRpb24pIG11c3QgaGF2ZSBtdWx0aXBsaWNpdGllcyB0aGF0IGRlZmluZSB0aGUgbWFwcGluZyBiZXR3ZWVuIHRoZSBjbGFzcyBpbnN0YW5jZXMgb2YgdGhlIHJlc3BlY3RpdmUgY2xhc3Nlcy4KCiMjIFR1dG9yaWFsCgpUaGUgdmlkZW8gdHV0b3JpYWwgYmVsb3cgZXhwbGFpbnMgaW4gbW9yZSBkZXRhaWwgdGhlIGNvbmNlcHQgb2YgYSByZWxhdGlvbnNoaXAgYmV0d2VlbiBvYmplY3RzIGFzIGEgbWFwcGluZyBiZXR3ZWVuIHR3byBzZXRzLCBvciBhIGZ1bmN0aW9uIHRoYXQgbWFwcyBhbiBpbnN0YW5jZSBvZiBjbGFzcyAqQSogdG8gemVybyBvciBtb3JlIGluc3RhbmNlcyBvZiBjbGFzcyAqQiouCgpgYGB7PWh0bWx9CjxpZnJhbWUgc3JjPSJodHRwczovL25vcnRoZWFzdGVybi5ob3N0ZWQucGFub3B0by5jb20vUGFub3B0by9QYWdlcy9FbWJlZC5hc3B4P2lkPTczMzVjZjFlLTIzMGQtNDg4Zi05ZTFlLWFkMmUwMDA1ODViMSZhbXA7YXV0b3BsYXk9ZmFsc2UmYW1wO29mZmVydmlld2VyPXRydWUmYW1wO3Nob3d0aXRsZT1mYWxzZSZhbXA7c2hvd2JyYW5kPWZhbHNlJmFtcDtzdGFydD0wJmFtcDtpbnRlcmFjdGl2aXR5PWFsbCIgd2lkdGg9IjQ4MCIgaGVpZ2h0PSIyNzAiIGZyYW1lYm9yZGVyPSIwIiBhbGxvdz0iYXV0b3BsYXk7IGZ1bGxzY3JlZW47IHBpY3R1cmUtaW4tcGljdHVyZSIgYWxsb3dmdWxsc2NyZWVuIGRhdGEtZXh0ZXJuYWw9IjEiPjwvaWZyYW1lPgpgYGAKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgRmlsZXMgJiBSZXNvdXJjZXMKCmBgYHtyIHppcEZpbGVzLCBlY2hvPUZBTFNFfQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgCiAgICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LAogICAgICAgICAgICAgICAgIHBhcmFtcyRudW1iZXIpCgp0ZXh0QUxpbmsgPSBwYXN0ZTAoIkFsbCBGaWxlcyBmb3IgTGVzc29uICIsIAogICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksIi4iLHBhcmFtcyRudW1iZXIpCgojIGRvd25sb2FkRmlsZXNMaW5rKCkgaXMgaW5jbHVkZWQgZnJvbSBfaW5zZXJ0MkRCLlIKa25pdHI6OnJhd19odG1sKGRvd25sb2FkRmlsZXNMaW5rKCIuIiwgemlwTmFtZSwgdGV4dEFMaW5rKSkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlZmVyZW5jZXMKCk5vbmUuCgojIyBFcnJhdGEKCltMZXQgdXMga25vd10oaHR0cHM6Ly9mb3JtLmpvdGZvcm0uY29tLzIxMjE4NzA3Mjc4NDE1Nyl7dGFyZ2V0PSJfYmxhbmsifS4K