Introduction

UML Class diagrams are one of many UML diagrams for describing various aspects of a software, data, business, or enterprise architecture. They are used for a number of purposes including object-oriented software design, business data models, and conceptual data models. In this course, we are using a subset of the UML Class diagram symbol set and modeling elements to visualize domain ontologies and conceptual data models.

Overview

Watch the narrated tutorial below before proceeding the the remaining lesson in order to can get context.

Relationships

Class diagrams show classes (entities of a domain), their attributes, and their relationships. UML distinguishes among several kinds of relationships, including four which are of particular interest for conceptual modeling: association, aggregation, and composition, and generalization. Additionally, there are implementation and dependency relationships, but those are of primary interest to software architects building object-oriented designs – we will omit those two relationships.

Association

An association is a domain-level connection between two classes where neither is dominant over the other. Associations can have an optional text label that explains the nature of the association. Additionally, all associations must be multiplicity constraints on both ends of the relationship.

A multiplicity constraint is in the form of n..m where n and m are the lower and upper bounds, respectively, and n ≤ m, and n ≥ 0 and m ≥ 1. A bound can be a specific scalar value, e.g., 1, 5, 52.

If the upper bound is not known or there is no specific upper bound then it can be left unspecified using *. If the lower and upper bounds are the same, a single bound suffices. So, 1..5, 0..*, and 52 are valid multiplicity constraints.

Note that * by itself is not considered an appropriate multiplicity constraint as there is no explicit lower bound. However, according to the UML Specification 2.5.1, * by itself implies a lower bound of 0, so * is the same as 0..*.

The diagram fragment below shows an example that includes associations only, along with labels, reading directionality indicator (►), and multiplicity. The reading direction is generally left-to-right and top-to-bottom but the directionality indicators allow for free-form placement of modeling elements.

The line itself should not have arrows as associations are bidirectional and equally valid in both directions. The arrow on an association line is useful for database design or software design to indicate which object has a reference (or pointer or foreign key) to the other object, but that is not appropriate for conceptual models as such models are intended to be implementation agnostic.

The UML Class Diagram fragment below illustrates these modeling elements.

The diagram has three classes: Passenger, Ride, and Driver. They are linked – or associated – and modeled with an association relationship. A passenger takes zero or more rides while a ride is for one or at most two passengers. The ride is driven by exactly one driver and a driver can drive any number of rides, including none.

Association Tutorial

In this short tutorial, Khoury Boston’s Prof. Schedlbauer goes through an example on how to define an association, label, directionality, and multiplicity.

He also explains the difference between association and aggregation.

Reading Multiplicities

Multiplicities are constraints or rules defined by the business domain and they can be different for the same pair of classes in different domains. In the above UML fragment, the multiplicity constraint between “Passenger” and “Ride” should be read as follow:

Any passenger may take several rides (the * in 0..*). Some Passengers do not take any rides (the 0 in 0..*). A ride is taken by up two two passengers – or – A ride is taken by no more than two passengers. Every ride must be taken by at least one passenger.

Multiplicities as Object Set Mappings

To establish a multiplicity, you take “one” instance from one class and ask to how many of the other class it is connected to, and vice versa. We are essentially defining a mapping between two sets of objects. A class can be thought of as a set of objects and we are building a mapping between the two.

The short tutorial below provides additional insight into how these mappings are established.

Aggregation

An aggregation relationships is a special form of association where one class in the relationship is the aggregate (collection) of the other class. This is an anti-symmetric whole-part relationship. Since an aggregation is an association, all of the properties of an association also apply to an aggregation.

Composition

A composition is a stronger and more restrictive form of aggregation. All of the properties of an aggregation also apply to composition. And, since aggregation is a special form of association, then by the rules of transitivity, all properties of associations also apply to composition. While a composition has a label, it is often omitted as the implied label is “contains” or “has a” and therefore does not add any additional insights.

Composition is also often used to imply that a “part” cannot exist independently of its “whole” or its container. For example, a room cannot exist independent of a house, so there’s a composition relationship between house (container) and room (part).

Of course, depending on the domain and its rules, the diagram might be different. For example, in the above diagram, it implies that a house can only have one garage, although the garage can have several spots in which to park cars. Naturally, there might be houses that have multiple, independent garages, but we are not modeling that.

Generalization

A generalization defines a class hierarchy indicating that a subclass is a special type of the superclass. All attributes applying to the superclass also apply, by definition, to the subclass. Generalization is a generalization-specialization taxonomy. This relationship is often implemented in object-oriented programming languages with inheritance.

In UML, a generalization is visualized with a hollow area pointing from the specialized class (subclass) toward its generalized class (superclass). We often use the phrase “is a type of” or “is a kind of”.

Generalization relationships are relationships between classes and not mapping between sets of objects, so there is no multiplicity or label. The diagram below illustrates a generalization hierarchy.

It shows that there are two “special” types (kinds) of members: honorary members and officers. Both are members and have all of the attributes and properties of a member but they each have unique properties just applicable to them. We often say that the subclass “inherits” the properties of its superclass, so in the above example, “Officer” inherits the attributes of “Member”, which means that an “Officer” has a name and a date joined and additionally has a role attribute – an attribute that only officers have and not all members in general.

Honorary members and officers can also be classified as members, but honorary members are a subset of all members; hence the term subclass for “Honorary Member” and for “Officer”. And all members is a superset of all special types of members; hence the term superclass for “Members”.

Object-Level Relationships

Associations, and implicitly, aggregations and compositions, are relationships among objects. Generalization is a taxonomy of classes and because of that multiplicity constraints do not apply to Generalization. One can look at classes as set of objects, e.g., class A is the set of all objects that have the structure, attributes, and properties of A. Objects can be viewed as instances of classes having specific values for the attributes and properties but conforming to all of the constraints defined by the class to which the objects belong.

UML Meta Model

The relationships and their “relationships” can be summarized in the UML meta model below.

Goal of Modeling

A common refrain among those new to conceptual and business data modeling is that since the implementation of association, aggregation, and composition doesn’t differ in a relational database or most object-oriented programming languages, then why does one care. The answer is simple: because the relationships exist in the business domain and therefore must be expressed. They express constraints and properties of the objects in the business domain. Just because some databases or programming languages are inadequate does not mean that we should ignore the constraints that are present.

Aggregation and Composition Patterns

There are several common “patterns” when modeling that are best expressed as either aggregation or as composition. For all aggregations and compositions, the aggregate/composite must in some way depend functionally or structurally on its components.

The relationships of aggregation and composition are always anti-symmetric and transitive, i.e., if A contains B, then B cannot contain A, and, if A contains B and B contains C, then A contains C.

Assembly-Parts Aggregation

An assembly-parts aggregation where a whole (assembly) is comprised of parts that retain their identity when they are contained in the whole. The whole does not cease to exist when parts are removed. Multiplicity constraints are used to specify whether the assembly must contain specific numbers of a part or whether the part of option. Many manufactured items are assembly-parts aggregations.

Of course, in the above example, engine would also be an assembly-parts aggregation of parts such as fuel pump, engine block, etc. The cost of the automobile is a derived value, calculated as the sum of the costs of the parts that comprise the car. A better model might be to have “Part” as the superclass (generalization) of “Engine” and “Wheel” and to contain cost and serialNo as attributes of “Part.”

The precise definitions of the classes, their attributes, and the multiplicity constraints depend on the business domain. For example, the above would be valid for new automobiles but not for “junk cars” that are salvaged for parts. In that scenario, an automobile has 0..1 engines and 0..4 wheels as some might be removed for salvage and resale.

Container-Content Aggregation

Defines a collection of parts where the parts bear no structural or functional relationship to each other, but there are rules that determine membership in the collection. It is very similar to the Organization-Member aggregation pattern below. An example of a container-content aggregation is a frame on a web page that displays ads. Whether an ad is displayed is subject to certain rules about size, content, payment, and interest to the web page viewer. The aggregation between web page and ad can also be considered a container-content aggregation. Of course, a web page has many more areas so the diagram below is only a fragment.

Organization-Member Aggregation

In this form of aggregation, members are part of an organization and the organization is defined as the collection of its members. For example, a cricket team (organization) consists of players (members) or a yacht club consists of members. The nature of the organization is its collection of members but members can come and go without the organization ceasing to exist. There may be a constraint on the minimum required number of members. For example, in Germany, a club (“Verein”) must have at least seven members in order for it can be recognized. Additionally, there may be rules on when a member may part of the organization, although such constraints are managed through application logic, database triggers, or in other ways.

Material-Object Composition

In this relationship pattern, the parts (materials) loose their identity when they are put into the composite (the object) and they cannot be removed once they are part of the composite. For example, paper is made from wood fibers, cotton, and glue. Once those parts are added to the object, they can no longer be removed. Phrases to look for during analysis include: is made from; consists of; is partly. Note that the diagram below does not include a quantity of each material – it would need to be included as part of another class if this were used in a manufacturing domain.

Portion-Ingredient Composition

This pattern is similar to Material-Object except that we view a whole (the composite) as a collection of portions of the whole. The parts are of the same class as the whole (a homomeric relationship).

Examples

  • a slice of pie is a portion of a whole pie
  • an inch is part of a foot.

Phrases to look for during analysis: portion of; references to measurements

Place-Area Composition

This pattern describes a link between similar classes where one is included in the other. Often applies to geographical domains.

For example, Palm Beach is located in Palm Beach County which in turn is located in Florida which is part of the United States which is part of North America, an so on.

This can also apply to real estate and building domains, e.g., an office is on a floor which is in a building. It is different from a container-content aggregation in that the parts cannot be removed. For example, one cannot remove Florida from the United States – of course, one could argue that cessation is an option and thus Florida could be removed from the United States or that Florida could merge with Georgia in a new state. Naturally, the exact rules depend on the domain and could change over time.

Collection-Members Composition

A collection-member composition where parts are permanently fused to the whole and there’s an ordering to the parts. For example, a weekly time sheet consists of daily time sheets or a flight reservation consists of flight segment reservations.

Conclusion

On many occasions some relationship can be viewed as falling into more than one pattern – the precise pattern classification does not matter. The purpose of the patterns is to present various situations where an analyst might discover aggregations or compositions rather than simple associations. When is doubt, make the relationship an association – it can always be refined into an aggregation or a composition when additional constraints are discovered.


Files & Resources

All Files for Lesson 30.155

Errata

Let us know.

LS0tCnRpdGxlOiAiUmVsYXRpb25zaGlwIFR5cGVzIGluIFVNTCBDbGFzcyBEaWFncmFtcyIKcGFyYW1zOgogIGNhdGVnb3J5OiAzMAogIHN0YWNrczogIjAsMCIKICBudW1iZXI6IDE1NQogIHRpbWU6IDQ1CiAgbGV2ZWw6IGJlZ2lubmVyCiAgdGFnczogVU1MLGdlbmVyYWxpemF0aW9uLGFzc29jaWF0aW9uLGFnZ3JlZ2F0aW9uCiAgZGVzY3JpcHRpb246ICJUaGlzIGxlc3NvbiBleHBsYWlucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFzc29jaWF0aW9uLAogICAgICAgICAgICAgICAgZ2VuZXJhbGl6YXRpb24sIGFnZ3JlZ2F0aW9uLCBhbmQgY29tcG9zaXRpb24gaW4gVU1MIENsYXNzIERpYWdyYW1zLgogICAgICAgICAgICAgICAgSXQgcHJlc2VudHMgYSBzZXQgb2YgY29tbW9uIHJlbGF0aW9uc2hpcCBwYXR0ZXJucyBhbmQgcHJvdmlkZXMKICAgICAgICAgICAgICAgIG1hbnkgZXhhbXBsZXMuIgpkYXRlOiAiPHNtYWxsPmByIFN5cy5EYXRlKClgPC9zbWFsbD4iCmF1dGhvcjogIjxzbWFsbD5NYXJ0aW4gU2NoZWRsYmF1ZXI8L3NtYWxsPiIKZW1haWw6ICJtLnNjaGVkbGJhdWVyQG5ldS5lZHUiCmFmZmlsaXRhdGlvbjogIk5vcnRoZWFzdGVybiBVbml2ZXJzaXR5IgpvdXRwdXQ6IAogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogc3BhY2VsYWIKICAgIGhpZ2hsaWdodDogdGFuZ28KLS0tCgotLS0KdGl0bGU6ICI8c21hbGw+YHIgcGFyYW1zJGNhdGVnb3J5YC5gciBwYXJhbXMkbnVtYmVyYDwvc21hbGw+PGJyLz48c3BhbiBzdHlsZT0nY29sb3I6ICMyRTQwNTM7IGZvbnQtc2l6ZTogMC45ZW0nPmByIHJtYXJrZG93bjo6bWV0YWRhdGEkdGl0bGVgPC9zcGFuPiIKLS0tCgpgYGB7ciBjb2RlPXhmdW46OnJlYWRfdXRmOChwYXN0ZTAoaGVyZTo6aGVyZSgpLCcvUi9faW5zZXJ0MkRCLlInKSksIGluY2x1ZGUgPSBGQUxTRX0KYGBgCgojIyBJbnRyb2R1Y3Rpb24KClVNTCBDbGFzcyBkaWFncmFtcyBhcmUgb25lIG9mIG1hbnkgVU1MIGRpYWdyYW1zIGZvciBkZXNjcmliaW5nIHZhcmlvdXMgYXNwZWN0cyBvZiBhIHNvZnR3YXJlLCBkYXRhLCBidXNpbmVzcywgb3IgZW50ZXJwcmlzZSBhcmNoaXRlY3R1cmUuIFRoZXkgYXJlIHVzZWQgZm9yIGEgbnVtYmVyIG9mIHB1cnBvc2VzIGluY2x1ZGluZyBvYmplY3Qtb3JpZW50ZWQgc29mdHdhcmUgZGVzaWduLCBidXNpbmVzcyBkYXRhIG1vZGVscywgYW5kIGNvbmNlcHR1YWwgZGF0YSBtb2RlbHMuIEluIHRoaXMgY291cnNlLCB3ZSBhcmUgdXNpbmcgYSBzdWJzZXQgb2YgdGhlIFVNTCBDbGFzcyBkaWFncmFtIHN5bWJvbCBzZXQgYW5kIG1vZGVsaW5nIGVsZW1lbnRzIHRvIHZpc3VhbGl6ZSBkb21haW4gb250b2xvZ2llcyBhbmQgY29uY2VwdHVhbCBkYXRhIG1vZGVscy4KCiMjIE92ZXJ2aWV3CgpXYXRjaCB0aGUgbmFycmF0ZWQgdHV0b3JpYWwgYmVsb3cgYmVmb3JlIHByb2NlZWRpbmcgdGhlIHRoZSByZW1haW5pbmcgbGVzc29uIGluIG9yZGVyIHRvIGNhbiBnZXQgY29udGV4dC4KCjxpZnJhbWUgc3JjPSJodHRwczovL3BsYXllci52aW1lby5jb20vdmlkZW8vNzkyNTU0MjY1P2JhZGdlPTAmYW1wO2F1dG9wYXVzZT0wJmFtcDtwbGF5ZXJfaWQ9MCZhbXA7YXBwX2lkPTU4NDc5IiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI3MCIgZnJhbWVib3JkZXI9IjAiIGFsbG93PSJhdXRvcGxheTsgZnVsbHNjcmVlbjsgcGljdHVyZS1pbi1waWN0dXJlIiB0aXRsZT0iUmVsYXRpb25zaGlwIFR5cGVzIGluIFVNTCBDbGFzcyBEaWFncmFtcyIgZGF0YS1leHRlcm5hbD0iMSI+Cgo8L2lmcmFtZT4KCiMjIFJlbGF0aW9uc2hpcHMKCkNsYXNzIGRpYWdyYW1zIHNob3cgY2xhc3NlcyAoZW50aXRpZXMgb2YgYSBkb21haW4pLCB0aGVpciBhdHRyaWJ1dGVzLCBhbmQgdGhlaXIgcmVsYXRpb25zaGlwcy4gVU1MIGRpc3Rpbmd1aXNoZXMgYW1vbmcgc2V2ZXJhbCBraW5kcyBvZiByZWxhdGlvbnNoaXBzLCBpbmNsdWRpbmcgZm91ciB3aGljaCBhcmUgb2YgcGFydGljdWxhciBpbnRlcmVzdCBmb3IgY29uY2VwdHVhbCBtb2RlbGluZzogYXNzb2NpYXRpb24sIGFnZ3JlZ2F0aW9uLCBhbmQgY29tcG9zaXRpb24sIGFuZCBnZW5lcmFsaXphdGlvbi4gQWRkaXRpb25hbGx5LCB0aGVyZSBhcmUgaW1wbGVtZW50YXRpb24gYW5kIGRlcGVuZGVuY3kgcmVsYXRpb25zaGlwcywgYnV0IHRob3NlIGFyZSBvZiBwcmltYXJ5IGludGVyZXN0IHRvIHNvZnR3YXJlIGFyY2hpdGVjdHMgYnVpbGRpbmcgb2JqZWN0LW9yaWVudGVkIGRlc2lnbnMgLS0gd2Ugd2lsbCBvbWl0IHRob3NlIHR3byByZWxhdGlvbnNoaXBzLgoKIyMjIEFzc29jaWF0aW9uCgpBbiBhc3NvY2lhdGlvbiBpcyBhIGRvbWFpbi1sZXZlbCBjb25uZWN0aW9uIGJldHdlZW4gdHdvIGNsYXNzZXMgd2hlcmUgbmVpdGhlciBpcyBkb21pbmFudCBvdmVyIHRoZSBvdGhlci4gQXNzb2NpYXRpb25zIGNhbiBoYXZlIGFuIG9wdGlvbmFsIHRleHQgbGFiZWwgdGhhdCBleHBsYWlucyB0aGUgbmF0dXJlIG9mIHRoZSBhc3NvY2lhdGlvbi4gQWRkaXRpb25hbGx5LCBhbGwgYXNzb2NpYXRpb25zIG11c3QgYmUgbXVsdGlwbGljaXR5IGNvbnN0cmFpbnRzIG9uIGJvdGggZW5kcyBvZiB0aGUgcmVsYXRpb25zaGlwLgoKQSBtdWx0aXBsaWNpdHkgY29uc3RyYWludCBpcyBpbiB0aGUgZm9ybSBvZiAqbi4ubSogd2hlcmUgKm4qIGFuZCAqbSogYXJlIHRoZSBsb3dlciBhbmQgdXBwZXIgYm91bmRzLCByZXNwZWN0aXZlbHksIGFuZCAqbiDiiaQgbSosIGFuZCAqbiDiiaUgMCogYW5kICptIOKJpSAxKi4gQSBib3VuZCBjYW4gYmUgYSBzcGVjaWZpYyBzY2FsYXIgdmFsdWUsICplLmcuKiwgKjEqLCAqNSosICo1MiouCgpJZiB0aGUgdXBwZXIgYm91bmQgaXMgbm90IGtub3duIG9yIHRoZXJlIGlzIG5vIHNwZWNpZmljIHVwcGVyIGJvdW5kIHRoZW4gaXQgY2FuIGJlIGxlZnQgdW5zcGVjaWZpZWQgdXNpbmcgXCouIElmIHRoZSBsb3dlciBhbmQgdXBwZXIgYm91bmRzIGFyZSB0aGUgc2FtZSwgYSBzaW5nbGUgYm91bmQgc3VmZmljZXMuIFNvLCAqMS4uNSosICowLi5cKiosIGFuZCAqNTIqIGFyZSB2YWxpZCBtdWx0aXBsaWNpdHkgY29uc3RyYWludHMuCgpOb3RlIHRoYXQgXCogYnkgaXRzZWxmIGlzIG5vdCBjb25zaWRlcmVkIGFuIGFwcHJvcHJpYXRlIG11bHRpcGxpY2l0eSBjb25zdHJhaW50IGFzIHRoZXJlIGlzIG5vIGV4cGxpY2l0IGxvd2VyIGJvdW5kLiBIb3dldmVyLCBhY2NvcmRpbmcgdG8gdGhlIFVNTCBTcGVjaWZpY2F0aW9uIDIuNS4xLCBcKiBieSBpdHNlbGYgaW1wbGllcyBhIGxvd2VyIGJvdW5kIG9mICowKiwgc28gXCogaXMgdGhlIHNhbWUgYXMgKjAuLlwqKi4KClRoZSBkaWFncmFtIGZyYWdtZW50IGJlbG93IHNob3dzIGFuIGV4YW1wbGUgdGhhdCBpbmNsdWRlcyBhc3NvY2lhdGlvbnMgb25seSwgYWxvbmcgd2l0aCBsYWJlbHMsIHJlYWRpbmcgZGlyZWN0aW9uYWxpdHkgaW5kaWNhdG9yICjilropLCBhbmQgbXVsdGlwbGljaXR5LiBUaGUgcmVhZGluZyBkaXJlY3Rpb24gaXMgZ2VuZXJhbGx5IGxlZnQtdG8tcmlnaHQgYW5kIHRvcC10by1ib3R0b20gYnV0IHRoZSBkaXJlY3Rpb25hbGl0eSBpbmRpY2F0b3JzIGFsbG93IGZvciBmcmVlLWZvcm0gcGxhY2VtZW50IG9mIG1vZGVsaW5nIGVsZW1lbnRzLgoKVGhlIGxpbmUgaXRzZWxmIHNob3VsZCBub3QgaGF2ZSBhcnJvd3MgYXMgYXNzb2NpYXRpb25zIGFyZSBiaWRpcmVjdGlvbmFsIGFuZCBlcXVhbGx5IHZhbGlkIGluIGJvdGggZGlyZWN0aW9ucy4gVGhlIGFycm93IG9uIGFuIGFzc29jaWF0aW9uIGxpbmUgaXMgdXNlZnVsIGZvciBkYXRhYmFzZSBkZXNpZ24gb3Igc29mdHdhcmUgZGVzaWduIHRvIGluZGljYXRlIHdoaWNoIG9iamVjdCBoYXMgYSByZWZlcmVuY2UgKG9yIHBvaW50ZXIgb3IgZm9yZWlnbiBrZXkpIHRvIHRoZSBvdGhlciBvYmplY3QsIGJ1dCB0aGF0IGlzIG5vdCBhcHByb3ByaWF0ZSBmb3IgY29uY2VwdHVhbCBtb2RlbHMgYXMgc3VjaCBtb2RlbHMgYXJlIGludGVuZGVkIHRvIGJlIGltcGxlbWVudGF0aW9uIGFnbm9zdGljLgoKVGhlIFVNTCBDbGFzcyBEaWFncmFtIGZyYWdtZW50IGJlbG93IGlsbHVzdHJhdGVzIHRoZXNlIG1vZGVsaW5nIGVsZW1lbnRzLgoKIVtdKGltYWdlcy9sLTMwLTE1NS11bWwtMS5qcGcpe3dpZHRoPSI1MCUifQoKVGhlIGRpYWdyYW0gaGFzIHRocmVlIGNsYXNzZXM6IFBhc3NlbmdlciwgUmlkZSwgYW5kIERyaXZlci4gVGhleSBhcmUgbGlua2VkIC0tIG9yIGFzc29jaWF0ZWQgLS0gYW5kIG1vZGVsZWQgd2l0aCBhbiBhc3NvY2lhdGlvbiByZWxhdGlvbnNoaXAuIEEgcGFzc2VuZ2VyIHRha2VzIHplcm8gb3IgbW9yZSByaWRlcyB3aGlsZSBhIHJpZGUgaXMgZm9yIG9uZSBvciBhdCBtb3N0IHR3byBwYXNzZW5nZXJzLiBUaGUgcmlkZSBpcyBkcml2ZW4gYnkgZXhhY3RseSBvbmUgZHJpdmVyIGFuZCBhIGRyaXZlciBjYW4gZHJpdmUgYW55IG51bWJlciBvZiByaWRlcywgaW5jbHVkaW5nIG5vbmUuCgojIyMjIEFzc29jaWF0aW9uIFR1dG9yaWFsCgpJbiB0aGlzIHNob3J0IHR1dG9yaWFsLCBLaG91cnkgQm9zdG9uJ3MgUHJvZi4gU2NoZWRsYmF1ZXIgZ29lcyB0aHJvdWdoIGFuIGV4YW1wbGUgb24gaG93IHRvIGRlZmluZSBhbiBhc3NvY2lhdGlvbiwgbGFiZWwsIGRpcmVjdGlvbmFsaXR5LCBhbmQgbXVsdGlwbGljaXR5LgoKSGUgYWxzbyBleHBsYWlucyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGFzc29jaWF0aW9uIGFuZCBhZ2dyZWdhdGlvbi4KCjxpZnJhbWUgc3R5bGU9ImJvcmRlcjogMXB4IHNvbGlkICM0NjQ2NDY7IiBzcmM9Imh0dHBzOi8vcGxheWVyLnZpbWVvLmNvbS92aWRlby82NzI4NzM4NDY/aD1jMWJhNGQ4YjUzIiB3aWR0aD0iNDgwIiBoZWlnaHQ9IjI4MCIgYWxsb3dmdWxsc2NyZWVuPSJhbGxvd2Z1bGxzY3JlZW4iIGFsbG93PSJhdXRvcGxheTsgZnVsbHNjcmVlbjsgcGljdHVyZS1pbi1waWN0dXJlIiBkYXRhLWV4dGVybmFsPSIxIj4KCjwvaWZyYW1lPgoKIyMjIFJlYWRpbmcgTXVsdGlwbGljaXRpZXMKCk11bHRpcGxpY2l0aWVzIGFyZSBjb25zdHJhaW50cyBvciBydWxlcyBkZWZpbmVkIGJ5IHRoZSBidXNpbmVzcyBkb21haW4gYW5kIHRoZXkgY2FuIGJlIGRpZmZlcmVudCBmb3IgdGhlIHNhbWUgcGFpciBvZiBjbGFzc2VzIGluIGRpZmZlcmVudCBkb21haW5zLiBJbiB0aGUgYWJvdmUgVU1MIGZyYWdtZW50LCB0aGUgbXVsdGlwbGljaXR5IGNvbnN0cmFpbnQgYmV0d2VlbiAiUGFzc2VuZ2VyIiBhbmQgIlJpZGUiIHNob3VsZCBiZSByZWFkIGFzIGZvbGxvdzoKCkFueSBwYXNzZW5nZXIgbWF5IHRha2Ugc2V2ZXJhbCByaWRlcyAodGhlIFwqIGluICowLi5cKiopLiBTb21lIFBhc3NlbmdlcnMgZG8gbm90IHRha2UgYW55IHJpZGVzICh0aGUgMCBpbiAqMC4uXCoqKS4gQSByaWRlIGlzIHRha2VuIGJ5IHVwIHR3byB0d28gcGFzc2VuZ2VycyAtLSBvciAtLSBBIHJpZGUgaXMgdGFrZW4gYnkgbm8gbW9yZSB0aGFuIHR3byBwYXNzZW5nZXJzLiBFdmVyeSByaWRlIG11c3QgYmUgdGFrZW4gYnkgYXQgbGVhc3Qgb25lIHBhc3Nlbmdlci4KCiMjIyBNdWx0aXBsaWNpdGllcyBhcyBPYmplY3QgU2V0IE1hcHBpbmdzCgpUbyBlc3RhYmxpc2ggYSBtdWx0aXBsaWNpdHksIHlvdSB0YWtlICJvbmUiIGluc3RhbmNlIGZyb20gb25lIGNsYXNzIGFuZCBhc2sgdG8gaG93IG1hbnkgb2YgdGhlIG90aGVyIGNsYXNzIGl0IGlzIGNvbm5lY3RlZCB0bywgYW5kIHZpY2UgdmVyc2EuIFdlIGFyZSBlc3NlbnRpYWxseSBkZWZpbmluZyBhIG1hcHBpbmcgYmV0d2VlbiB0d28gc2V0cyBvZiBvYmplY3RzLiBBIGNsYXNzIGNhbiBiZSB0aG91Z2h0IG9mIGFzIGEgc2V0IG9mIG9iamVjdHMgYW5kIHdlIGFyZSBidWlsZGluZyBhIG1hcHBpbmcgYmV0d2VlbiB0aGUgdHdvLgoKVGhlIHNob3J0IHR1dG9yaWFsIGJlbG93IHByb3ZpZGVzIGFkZGl0aW9uYWwgaW5zaWdodCBpbnRvIGhvdyB0aGVzZSBtYXBwaW5ncyBhcmUgZXN0YWJsaXNoZWQuCgo8aWZyYW1lIHN0eWxlPSJib3JkZXI6IDFweCBzb2xpZCAjNDY0NjQ2OyIgc3JjPSJodHRwczovL25vcnRoZWFzdGVybi5ob3N0ZWQucGFub3B0by5jb20vUGFub3B0by9QYWdlcy9FbWJlZC5hc3B4P2lkPTczMzVjZjFlLTIzMGQtNDg4Zi05ZTFlLWFkMmUwMDA1ODViMSZhbXA7YXV0b3BsYXk9ZmFsc2UmYW1wO29mZmVydmlld2VyPWZhbHNlJmFtcDtzaG93dGl0bGU9ZmFsc2UmYW1wO3Nob3dicmFuZD1mYWxzZSZhbXA7c3RhcnQ9MCZhbXA7aW50ZXJhY3Rpdml0eT1hbGwiIHdpZHRoPSI0ODAiIGhlaWdodD0iMjcwIiBhbGxvd2Z1bGxzY3JlZW49ImFsbG93ZnVsbHNjcmVlbiIgYWxsb3c9ImF1dG9wbGF5IiBkYXRhLWV4dGVybmFsPSIxIj4KCjwvaWZyYW1lPgoKIyMjIEFnZ3JlZ2F0aW9uCgpBbiBhZ2dyZWdhdGlvbiByZWxhdGlvbnNoaXBzIGlzIGEgc3BlY2lhbCBmb3JtIG9mIGFzc29jaWF0aW9uIHdoZXJlIG9uZSBjbGFzcyBpbiB0aGUgcmVsYXRpb25zaGlwIGlzIHRoZSBhZ2dyZWdhdGUgKGNvbGxlY3Rpb24pIG9mIHRoZSBvdGhlciBjbGFzcy4gVGhpcyBpcyBhbiBhbnRpLXN5bW1ldHJpYyB3aG9sZS1wYXJ0IHJlbGF0aW9uc2hpcC4gU2luY2UgYW4gYWdncmVnYXRpb24gaXMgYW4gYXNzb2NpYXRpb24sIGFsbCBvZiB0aGUgcHJvcGVydGllcyBvZiBhbiBhc3NvY2lhdGlvbiBhbHNvIGFwcGx5IHRvIGFuIGFnZ3JlZ2F0aW9uLgoKIyMjIENvbXBvc2l0aW9uCgpBIGNvbXBvc2l0aW9uIGlzIGEgc3Ryb25nZXIgYW5kIG1vcmUgcmVzdHJpY3RpdmUgZm9ybSBvZiBhZ2dyZWdhdGlvbi4gQWxsIG9mIHRoZSBwcm9wZXJ0aWVzIG9mIGFuIGFnZ3JlZ2F0aW9uIGFsc28gYXBwbHkgdG8gY29tcG9zaXRpb24uIEFuZCwgc2luY2UgYWdncmVnYXRpb24gaXMgYSBzcGVjaWFsIGZvcm0gb2YgYXNzb2NpYXRpb24sIHRoZW4gYnkgdGhlIHJ1bGVzIG9mIHRyYW5zaXRpdml0eSwgYWxsIHByb3BlcnRpZXMgb2YgYXNzb2NpYXRpb25zIGFsc28gYXBwbHkgdG8gY29tcG9zaXRpb24uIFdoaWxlIGEgY29tcG9zaXRpb24gaGFzIGEgbGFiZWwsIGl0IGlzIG9mdGVuIG9taXR0ZWQgYXMgdGhlIGltcGxpZWQgbGFiZWwgaXMgImNvbnRhaW5zIiBvciAiaGFzIGEiIGFuZCB0aGVyZWZvcmUgZG9lcyBub3QgYWRkIGFueSBhZGRpdGlvbmFsIGluc2lnaHRzLgoKQ29tcG9zaXRpb24gaXMgYWxzbyBvZnRlbiB1c2VkIHRvIGltcGx5IHRoYXQgYSAicGFydCIgY2Fubm90IGV4aXN0IGluZGVwZW5kZW50bHkgb2YgaXRzICJ3aG9sZSIgb3IgaXRzIGNvbnRhaW5lci4gRm9yIGV4YW1wbGUsIGEgcm9vbSBjYW5ub3QgZXhpc3QgaW5kZXBlbmRlbnQgb2YgYSBob3VzZSwgc28gdGhlcmUncyBhIGNvbXBvc2l0aW9uIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGhvdXNlIChjb250YWluZXIpIGFuZCByb29tIChwYXJ0KS4KCiFbXShpbWFnZXMvbC0zMC0xNTUtdW1sLTIuanBnKXt3aWR0aD0iNjAlIn0KCk9mIGNvdXJzZSwgZGVwZW5kaW5nIG9uIHRoZSBkb21haW4gYW5kIGl0cyBydWxlcywgdGhlIGRpYWdyYW0gbWlnaHQgYmUgZGlmZmVyZW50LiBGb3IgZXhhbXBsZSwgaW4gdGhlIGFib3ZlIGRpYWdyYW0sIGl0IGltcGxpZXMgdGhhdCBhIGhvdXNlIGNhbiBvbmx5IGhhdmUgb25lIGdhcmFnZSwgYWx0aG91Z2ggdGhlIGdhcmFnZSBjYW4gaGF2ZSBzZXZlcmFsIHNwb3RzIGluIHdoaWNoIHRvIHBhcmsgY2Fycy4gTmF0dXJhbGx5LCB0aGVyZSBtaWdodCBiZSBob3VzZXMgdGhhdCBoYXZlIG11bHRpcGxlLCBpbmRlcGVuZGVudCBnYXJhZ2VzLCBidXQgd2UgYXJlIG5vdCBtb2RlbGluZyB0aGF0LgoKIyMjIEdlbmVyYWxpemF0aW9uCgpBIGdlbmVyYWxpemF0aW9uIGRlZmluZXMgYSBjbGFzcyBoaWVyYXJjaHkgaW5kaWNhdGluZyB0aGF0IGEgc3ViY2xhc3MgaXMgYSBzcGVjaWFsIHR5cGUgb2YgdGhlIHN1cGVyY2xhc3MuIEFsbCBhdHRyaWJ1dGVzIGFwcGx5aW5nIHRvIHRoZSBzdXBlcmNsYXNzIGFsc28gYXBwbHksIGJ5IGRlZmluaXRpb24sIHRvIHRoZSBzdWJjbGFzcy4gR2VuZXJhbGl6YXRpb24gaXMgYSBnZW5lcmFsaXphdGlvbi1zcGVjaWFsaXphdGlvbiB0YXhvbm9teS4gVGhpcyByZWxhdGlvbnNoaXAgaXMgb2Z0ZW4gaW1wbGVtZW50ZWQgaW4gb2JqZWN0LW9yaWVudGVkIHByb2dyYW1taW5nIGxhbmd1YWdlcyB3aXRoICppbmhlcml0YW5jZSouCgpJbiBVTUwsIGEgZ2VuZXJhbGl6YXRpb24gaXMgdmlzdWFsaXplZCB3aXRoIGEgaG9sbG93IGFyZWEgcG9pbnRpbmcgZnJvbSB0aGUgc3BlY2lhbGl6ZWQgY2xhc3MgKHN1YmNsYXNzKSB0b3dhcmQgaXRzIGdlbmVyYWxpemVkIGNsYXNzIChzdXBlcmNsYXNzKS4gV2Ugb2Z0ZW4gdXNlIHRoZSBwaHJhc2UgImlzIGEgdHlwZSBvZiIgb3IgImlzIGEga2luZCBvZiIuCgpHZW5lcmFsaXphdGlvbiByZWxhdGlvbnNoaXBzIGFyZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gY2xhc3NlcyBhbmQgbm90IG1hcHBpbmcgYmV0d2VlbiBzZXRzIG9mIG9iamVjdHMsIHNvIHRoZXJlIGlzIG5vIG11bHRpcGxpY2l0eSBvciBsYWJlbC4gVGhlIGRpYWdyYW0gYmVsb3cgaWxsdXN0cmF0ZXMgYSBnZW5lcmFsaXphdGlvbiBoaWVyYXJjaHkuCgohW10oaW1hZ2VzL2wtMzAtMTU1LXVtbC03LmpwZyl7d2lkdGg9IjYwJSJ9CgpJdCBzaG93cyB0aGF0IHRoZXJlIGFyZSB0d28gInNwZWNpYWwiIHR5cGVzIChraW5kcykgb2YgbWVtYmVyczogaG9ub3JhcnkgbWVtYmVycyBhbmQgb2ZmaWNlcnMuIEJvdGggYXJlIG1lbWJlcnMgYW5kIGhhdmUgYWxsIG9mIHRoZSBhdHRyaWJ1dGVzIGFuZCBwcm9wZXJ0aWVzIG9mIGEgbWVtYmVyIGJ1dCB0aGV5IGVhY2ggaGF2ZSB1bmlxdWUgcHJvcGVydGllcyBqdXN0IGFwcGxpY2FibGUgdG8gdGhlbS4gV2Ugb2Z0ZW4gc2F5IHRoYXQgdGhlIHN1YmNsYXNzICJpbmhlcml0cyIgdGhlIHByb3BlcnRpZXMgb2YgaXRzIHN1cGVyY2xhc3MsIHNvIGluIHRoZSBhYm92ZSBleGFtcGxlLCAiT2ZmaWNlciIgaW5oZXJpdHMgdGhlIGF0dHJpYnV0ZXMgb2YgIk1lbWJlciIsIHdoaWNoIG1lYW5zIHRoYXQgYW4gIk9mZmljZXIiIGhhcyBhIG5hbWUgYW5kIGEgZGF0ZSBqb2luZWQgYW5kICphZGRpdGlvbmFsbHkqIGhhcyBhIHJvbGUgYXR0cmlidXRlIC0tIGFuIGF0dHJpYnV0ZSB0aGF0IG9ubHkgb2ZmaWNlcnMgaGF2ZSBhbmQgbm90IGFsbCBtZW1iZXJzIGluIGdlbmVyYWwuCgpIb25vcmFyeSBtZW1iZXJzIGFuZCBvZmZpY2VycyBjYW4gYWxzbyBiZSBjbGFzc2lmaWVkIGFzIG1lbWJlcnMsIGJ1dCBob25vcmFyeSBtZW1iZXJzIGFyZSBhIHN1YnNldCBvZiBhbGwgbWVtYmVyczsgaGVuY2UgdGhlIHRlcm0gKnN1YmNsYXNzKiBmb3IgIkhvbm9yYXJ5IE1lbWJlciIgYW5kIGZvciAiT2ZmaWNlciIuIEFuZCBhbGwgbWVtYmVycyBpcyBhIHN1cGVyc2V0IG9mIGFsbCBzcGVjaWFsIHR5cGVzIG9mIG1lbWJlcnM7IGhlbmNlIHRoZSB0ZXJtICpzdXBlcmNsYXNzKiBmb3IgIk1lbWJlcnMiLgoKIyMjIE9iamVjdC1MZXZlbCBSZWxhdGlvbnNoaXBzCgpBc3NvY2lhdGlvbnMsIGFuZCBpbXBsaWNpdGx5LCBhZ2dyZWdhdGlvbnMgYW5kIGNvbXBvc2l0aW9ucywgYXJlIHJlbGF0aW9uc2hpcHMgYW1vbmcgb2JqZWN0cy4gR2VuZXJhbGl6YXRpb24gaXMgYSB0YXhvbm9teSBvZiBjbGFzc2VzIGFuZCBiZWNhdXNlIG9mIHRoYXQgbXVsdGlwbGljaXR5IGNvbnN0cmFpbnRzIGRvIG5vdCBhcHBseSB0byBHZW5lcmFsaXphdGlvbi4gT25lIGNhbiBsb29rIGF0IGNsYXNzZXMgYXMgc2V0IG9mIG9iamVjdHMsIGUuZy4sIGNsYXNzIEEgaXMgdGhlIHNldCBvZiBhbGwgb2JqZWN0cyB0aGF0IGhhdmUgdGhlIHN0cnVjdHVyZSwgYXR0cmlidXRlcywgYW5kIHByb3BlcnRpZXMgb2YgQS4gT2JqZWN0cyBjYW4gYmUgdmlld2VkIGFzIGluc3RhbmNlcyBvZiBjbGFzc2VzIGhhdmluZyBzcGVjaWZpYyB2YWx1ZXMgZm9yIHRoZSBhdHRyaWJ1dGVzIGFuZCBwcm9wZXJ0aWVzIGJ1dCBjb25mb3JtaW5nIHRvIGFsbCBvZiB0aGUgY29uc3RyYWludHMgZGVmaW5lZCBieSB0aGUgY2xhc3MgdG8gd2hpY2ggdGhlIG9iamVjdHMgYmVsb25nLgoKIyMgVU1MIE1ldGEgTW9kZWwKClRoZSByZWxhdGlvbnNoaXBzIGFuZCB0aGVpciAicmVsYXRpb25zaGlwcyIgY2FuIGJlIHN1bW1hcml6ZWQgaW4gdGhlIFVNTCBtZXRhIG1vZGVsIGJlbG93LgoKIVtdKGltYWdlcy9sLTMwLTE1NS11bWwtbWV0YS1tb2RlbC5qcGcpe3dpZHRoPSI2MCUifQoKIyMgR29hbCBvZiBNb2RlbGluZwoKQSBjb21tb24gcmVmcmFpbiBhbW9uZyB0aG9zZSBuZXcgdG8gY29uY2VwdHVhbCBhbmQgYnVzaW5lc3MgZGF0YSBtb2RlbGluZyBpcyB0aGF0IHNpbmNlIHRoZSBpbXBsZW1lbnRhdGlvbiBvZiBhc3NvY2lhdGlvbiwgYWdncmVnYXRpb24sIGFuZCBjb21wb3NpdGlvbiBkb2Vzbid0IGRpZmZlciBpbiBhIHJlbGF0aW9uYWwgZGF0YWJhc2Ugb3IgbW9zdCBvYmplY3Qtb3JpZW50ZWQgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzLCB0aGVuIHdoeSBkb2VzIG9uZSBjYXJlLiBUaGUgYW5zd2VyIGlzIHNpbXBsZTogYmVjYXVzZSB0aGUgcmVsYXRpb25zaGlwcyBleGlzdCBpbiB0aGUgYnVzaW5lc3MgZG9tYWluIGFuZCB0aGVyZWZvcmUgbXVzdCBiZSBleHByZXNzZWQuIFRoZXkgZXhwcmVzcyBjb25zdHJhaW50cyBhbmQgcHJvcGVydGllcyBvZiB0aGUgb2JqZWN0cyBpbiB0aGUgYnVzaW5lc3MgZG9tYWluLiBKdXN0IGJlY2F1c2Ugc29tZSBkYXRhYmFzZXMgb3IgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2VzIGFyZSBpbmFkZXF1YXRlIGRvZXMgbm90IG1lYW4gdGhhdCB3ZSBzaG91bGQgaWdub3JlIHRoZSBjb25zdHJhaW50cyB0aGF0IGFyZSBwcmVzZW50LgoKIyMgQWdncmVnYXRpb24gYW5kIENvbXBvc2l0aW9uIFBhdHRlcm5zCgpUaGVyZSBhcmUgc2V2ZXJhbCBjb21tb24gInBhdHRlcm5zIiB3aGVuIG1vZGVsaW5nIHRoYXQgYXJlIGJlc3QgZXhwcmVzc2VkIGFzIGVpdGhlciBhZ2dyZWdhdGlvbiBvciBhcyBjb21wb3NpdGlvbi4gRm9yIGFsbCBhZ2dyZWdhdGlvbnMgYW5kIGNvbXBvc2l0aW9ucywgdGhlIGFnZ3JlZ2F0ZS9jb21wb3NpdGUgbXVzdCBpbiBzb21lIHdheSBkZXBlbmQgZnVuY3Rpb25hbGx5IG9yIHN0cnVjdHVyYWxseSBvbiBpdHMgY29tcG9uZW50cy4KClRoZSByZWxhdGlvbnNoaXBzIG9mIGFnZ3JlZ2F0aW9uIGFuZCBjb21wb3NpdGlvbiBhcmUgYWx3YXlzIGFudGktc3ltbWV0cmljIGFuZCB0cmFuc2l0aXZlLCAqaS5lLiosIGlmICoqQSoqIGNvbnRhaW5zICoqQioqLCB0aGVuICoqQioqIGNhbm5vdCBjb250YWluICoqQSoqLCBhbmQsIGlmICoqQSoqIGNvbnRhaW5zICoqQioqIGFuZCAqKkIqKiBjb250YWlucyAqKkMqKiwgdGhlbiAqKkEqKiBjb250YWlucyAqKkMqKi4KCiMjIyBBc3NlbWJseS1QYXJ0cyBBZ2dyZWdhdGlvbgoKQW4gYXNzZW1ibHktcGFydHMgYWdncmVnYXRpb24gd2hlcmUgYSB3aG9sZSAoYXNzZW1ibHkpIGlzIGNvbXByaXNlZCBvZiBwYXJ0cyB0aGF0IHJldGFpbiB0aGVpciBpZGVudGl0eSB3aGVuIHRoZXkgYXJlIGNvbnRhaW5lZCBpbiB0aGUgd2hvbGUuIFRoZSB3aG9sZSBkb2VzIG5vdCBjZWFzZSB0byBleGlzdCB3aGVuIHBhcnRzIGFyZSByZW1vdmVkLiBNdWx0aXBsaWNpdHkgY29uc3RyYWludHMgYXJlIHVzZWQgdG8gc3BlY2lmeSB3aGV0aGVyIHRoZSBhc3NlbWJseSBtdXN0IGNvbnRhaW4gc3BlY2lmaWMgbnVtYmVycyBvZiBhIHBhcnQgb3Igd2hldGhlciB0aGUgcGFydCBvZiBvcHRpb24uIE1hbnkgbWFudWZhY3R1cmVkIGl0ZW1zIGFyZSBhc3NlbWJseS1wYXJ0cyBhZ2dyZWdhdGlvbnMuCgohW10oaW1hZ2VzL2wtMzAtMTU1LXVtbC0zLmpwZyl7d2lkdGg9IjYwJSJ9CgpPZiBjb3Vyc2UsIGluIHRoZSBhYm92ZSBleGFtcGxlLCBlbmdpbmUgd291bGQgYWxzbyBiZSBhbiBhc3NlbWJseS1wYXJ0cyBhZ2dyZWdhdGlvbiBvZiBwYXJ0cyBzdWNoIGFzIGZ1ZWwgcHVtcCwgZW5naW5lIGJsb2NrLCBldGMuIFRoZSBjb3N0IG9mIHRoZSBhdXRvbW9iaWxlIGlzIGEgZGVyaXZlZCB2YWx1ZSwgY2FsY3VsYXRlZCBhcyB0aGUgc3VtIG9mIHRoZSBjb3N0cyBvZiB0aGUgcGFydHMgdGhhdCBjb21wcmlzZSB0aGUgY2FyLiBBIGJldHRlciBtb2RlbCBtaWdodCBiZSB0byBoYXZlICJQYXJ0IiBhcyB0aGUgc3VwZXJjbGFzcyAoZ2VuZXJhbGl6YXRpb24pIG9mICJFbmdpbmUiIGFuZCAiV2hlZWwiIGFuZCB0byBjb250YWluICpjb3N0KiBhbmQgKnNlcmlhbE5vKiBhcyBhdHRyaWJ1dGVzIG9mICJQYXJ0LiIKClRoZSBwcmVjaXNlIGRlZmluaXRpb25zIG9mIHRoZSBjbGFzc2VzLCB0aGVpciBhdHRyaWJ1dGVzLCBhbmQgdGhlIG11bHRpcGxpY2l0eSBjb25zdHJhaW50cyBkZXBlbmQgb24gdGhlIGJ1c2luZXNzIGRvbWFpbi4gRm9yIGV4YW1wbGUsIHRoZSBhYm92ZSB3b3VsZCBiZSB2YWxpZCBmb3IgbmV3IGF1dG9tb2JpbGVzIGJ1dCBub3QgZm9yICJqdW5rIGNhcnMiIHRoYXQgYXJlIHNhbHZhZ2VkIGZvciBwYXJ0cy4gSW4gdGhhdCBzY2VuYXJpbywgYW4gYXV0b21vYmlsZSBoYXMgKjAuLjEqIGVuZ2luZXMgYW5kICowLi40KiB3aGVlbHMgYXMgc29tZSBtaWdodCBiZSByZW1vdmVkIGZvciBzYWx2YWdlIGFuZCByZXNhbGUuCgojIyMgQ29udGFpbmVyLUNvbnRlbnQgQWdncmVnYXRpb24KCkRlZmluZXMgYSBjb2xsZWN0aW9uIG9mIHBhcnRzIHdoZXJlIHRoZSBwYXJ0cyBiZWFyIG5vIHN0cnVjdHVyYWwgb3IgZnVuY3Rpb25hbCByZWxhdGlvbnNoaXAgdG8gZWFjaCBvdGhlciwgYnV0IHRoZXJlIGFyZSBydWxlcyB0aGF0IGRldGVybWluZSBtZW1iZXJzaGlwIGluIHRoZSBjb2xsZWN0aW9uLiBJdCBpcyB2ZXJ5IHNpbWlsYXIgdG8gdGhlIE9yZ2FuaXphdGlvbi1NZW1iZXIgYWdncmVnYXRpb24gcGF0dGVybiBiZWxvdy4gQW4gZXhhbXBsZSBvZiBhIGNvbnRhaW5lci1jb250ZW50IGFnZ3JlZ2F0aW9uIGlzIGEgZnJhbWUgb24gYSB3ZWIgcGFnZSB0aGF0IGRpc3BsYXlzIGFkcy4gV2hldGhlciBhbiBhZCBpcyBkaXNwbGF5ZWQgaXMgc3ViamVjdCB0byBjZXJ0YWluIHJ1bGVzIGFib3V0IHNpemUsIGNvbnRlbnQsIHBheW1lbnQsIGFuZCBpbnRlcmVzdCB0byB0aGUgd2ViIHBhZ2Ugdmlld2VyLiBUaGUgYWdncmVnYXRpb24gYmV0d2VlbiB3ZWIgcGFnZSBhbmQgYWQgY2FuIGFsc28gYmUgY29uc2lkZXJlZCBhIGNvbnRhaW5lci1jb250ZW50IGFnZ3JlZ2F0aW9uLiBPZiBjb3Vyc2UsIGEgd2ViIHBhZ2UgaGFzIG1hbnkgbW9yZSBhcmVhcyBzbyB0aGUgZGlhZ3JhbSBiZWxvdyBpcyBvbmx5IGEgZnJhZ21lbnQuCgohW10oaW1hZ2VzL2wtMzAtMTU1LXVtbC00LmpwZyl7d2lkdGg9IjYwJSJ9CgojIyMgT3JnYW5pemF0aW9uLU1lbWJlciBBZ2dyZWdhdGlvbgoKSW4gdGhpcyBmb3JtIG9mIGFnZ3JlZ2F0aW9uLCBtZW1iZXJzIGFyZSBwYXJ0IG9mIGFuIG9yZ2FuaXphdGlvbiBhbmQgdGhlIG9yZ2FuaXphdGlvbiBpcyBkZWZpbmVkIGFzIHRoZSBjb2xsZWN0aW9uIG9mIGl0cyBtZW1iZXJzLiBGb3IgZXhhbXBsZSwgYSBjcmlja2V0IHRlYW0gKG9yZ2FuaXphdGlvbikgY29uc2lzdHMgb2YgcGxheWVycyAobWVtYmVycykgb3IgYSB5YWNodCBjbHViIGNvbnNpc3RzIG9mIG1lbWJlcnMuIFRoZSBuYXR1cmUgb2YgdGhlIG9yZ2FuaXphdGlvbiBpcyBpdHMgY29sbGVjdGlvbiBvZiBtZW1iZXJzIGJ1dCBtZW1iZXJzIGNhbiBjb21lIGFuZCBnbyB3aXRob3V0IHRoZSBvcmdhbml6YXRpb24gY2Vhc2luZyB0byBleGlzdC4gVGhlcmUgbWF5IGJlIGEgY29uc3RyYWludCBvbiB0aGUgbWluaW11bSByZXF1aXJlZCBudW1iZXIgb2YgbWVtYmVycy4gRm9yIGV4YW1wbGUsIGluIEdlcm1hbnksIGEgY2x1YiAoIlZlcmVpbiIpIG11c3QgaGF2ZSBhdCBsZWFzdCBzZXZlbiBtZW1iZXJzIGluIG9yZGVyIGZvciBpdCBjYW4gYmUgcmVjb2duaXplZC4gQWRkaXRpb25hbGx5LCB0aGVyZSBtYXkgYmUgcnVsZXMgb24gd2hlbiBhIG1lbWJlciBtYXkgcGFydCBvZiB0aGUgb3JnYW5pemF0aW9uLCBhbHRob3VnaCBzdWNoIGNvbnN0cmFpbnRzIGFyZSBtYW5hZ2VkIHRocm91Z2ggYXBwbGljYXRpb24gbG9naWMsIGRhdGFiYXNlIHRyaWdnZXJzLCBvciBpbiBvdGhlciB3YXlzLgoKIVtdKGltYWdlcy9sLTMwLTE1NS11bWwtNS5qcGcpe3dpZHRoPSI2MCUifQoKIyMjIE1hdGVyaWFsLU9iamVjdCBDb21wb3NpdGlvbgoKSW4gdGhpcyByZWxhdGlvbnNoaXAgcGF0dGVybiwgdGhlIHBhcnRzIChtYXRlcmlhbHMpIGxvb3NlIHRoZWlyIGlkZW50aXR5IHdoZW4gdGhleSBhcmUgcHV0IGludG8gdGhlIGNvbXBvc2l0ZSAodGhlIG9iamVjdCkgYW5kIHRoZXkgY2Fubm90IGJlIHJlbW92ZWQgb25jZSB0aGV5IGFyZSBwYXJ0IG9mIHRoZSBjb21wb3NpdGUuIEZvciBleGFtcGxlLCBwYXBlciBpcyBtYWRlIGZyb20gd29vZCBmaWJlcnMsIGNvdHRvbiwgYW5kIGdsdWUuIE9uY2UgdGhvc2UgcGFydHMgYXJlIGFkZGVkIHRvIHRoZSBvYmplY3QsIHRoZXkgY2FuIG5vIGxvbmdlciBiZSByZW1vdmVkLiBQaHJhc2VzIHRvIGxvb2sgZm9yIGR1cmluZyBhbmFseXNpcyBpbmNsdWRlOiBpcyBtYWRlIGZyb207IGNvbnNpc3RzIG9mOyBpcyBwYXJ0bHkuIE5vdGUgdGhhdCB0aGUgZGlhZ3JhbSBiZWxvdyBkb2VzIG5vdCBpbmNsdWRlIGEgcXVhbnRpdHkgb2YgZWFjaCBtYXRlcmlhbCAtLSBpdCB3b3VsZCBuZWVkIHRvIGJlIGluY2x1ZGVkIGFzIHBhcnQgb2YgYW5vdGhlciBjbGFzcyBpZiB0aGlzIHdlcmUgdXNlZCBpbiBhIG1hbnVmYWN0dXJpbmcgZG9tYWluLgoKIVtdKGltYWdlcy9sLTMwLTE1NS11bWwtNi5qcGcpe3dpZHRoPSI2MCUifQoKIyMjIFBvcnRpb24tSW5ncmVkaWVudCBDb21wb3NpdGlvbgoKVGhpcyBwYXR0ZXJuIGlzIHNpbWlsYXIgdG8gKk1hdGVyaWFsLU9iamVjdCogZXhjZXB0IHRoYXQgd2UgdmlldyBhIHdob2xlICh0aGUgY29tcG9zaXRlKSBhcyBhIGNvbGxlY3Rpb24gb2YgcG9ydGlvbnMgb2YgdGhlIHdob2xlLiBUaGUgcGFydHMgYXJlIG9mIHRoZSBzYW1lIGNsYXNzIGFzIHRoZSB3aG9sZSAoYSBbaG9tb21lcmljXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ib21vbWVyaWMpIHJlbGF0aW9uc2hpcCkuCgoqKkV4YW1wbGVzKioKCi0gICBhIHNsaWNlIG9mIHBpZSBpcyBhIHBvcnRpb24gb2YgYSB3aG9sZSBwaWUKLSAgIGFuIGluY2ggaXMgcGFydCBvZiBhIGZvb3QuCgpQaHJhc2VzIHRvIGxvb2sgZm9yIGR1cmluZyBhbmFseXNpczogcG9ydGlvbiBvZjsgcmVmZXJlbmNlcyB0byBtZWFzdXJlbWVudHMKCiMjIyBQbGFjZS1BcmVhIENvbXBvc2l0aW9uCgpUaGlzIHBhdHRlcm4gZGVzY3JpYmVzIGEgbGluayBiZXR3ZWVuIHNpbWlsYXIgY2xhc3NlcyB3aGVyZSBvbmUgaXMgaW5jbHVkZWQgaW4gdGhlIG90aGVyLiBPZnRlbiBhcHBsaWVzIHRvIGdlb2dyYXBoaWNhbCBkb21haW5zLgoKRm9yIGV4YW1wbGUsIFBhbG0gQmVhY2ggaXMgbG9jYXRlZCBpbiBQYWxtIEJlYWNoIENvdW50eSB3aGljaCBpbiB0dXJuIGlzIGxvY2F0ZWQgaW4gRmxvcmlkYSB3aGljaCBpcyBwYXJ0IG9mIHRoZSBVbml0ZWQgU3RhdGVzIHdoaWNoIGlzIHBhcnQgb2YgTm9ydGggQW1lcmljYSwgYW4gc28gb24uCgpUaGlzIGNhbiBhbHNvIGFwcGx5IHRvIHJlYWwgZXN0YXRlIGFuZCBidWlsZGluZyBkb21haW5zLCAqZS5nLiosIGFuIG9mZmljZSBpcyBvbiBhIGZsb29yIHdoaWNoIGlzIGluIGEgYnVpbGRpbmcuIEl0IGlzIGRpZmZlcmVudCBmcm9tIGEgY29udGFpbmVyLWNvbnRlbnQgYWdncmVnYXRpb24gaW4gdGhhdCB0aGUgcGFydHMgY2Fubm90IGJlIHJlbW92ZWQuIEZvciBleGFtcGxlLCBvbmUgY2Fubm90IHJlbW92ZSBGbG9yaWRhIGZyb20gdGhlIFVuaXRlZCBTdGF0ZXMgLS0gb2YgY291cnNlLCBvbmUgY291bGQgYXJndWUgdGhhdCBjZXNzYXRpb24gaXMgYW4gb3B0aW9uIGFuZCB0aHVzIEZsb3JpZGEgY291bGQgYmUgcmVtb3ZlZCBmcm9tIHRoZSBVbml0ZWQgU3RhdGVzIG9yIHRoYXQgRmxvcmlkYSBjb3VsZCBtZXJnZSB3aXRoIEdlb3JnaWEgaW4gYSBuZXcgc3RhdGUuIE5hdHVyYWxseSwgdGhlIGV4YWN0IHJ1bGVzIGRlcGVuZCBvbiB0aGUgZG9tYWluIGFuZCBjb3VsZCBjaGFuZ2Ugb3ZlciB0aW1lLgoKIyMjIENvbGxlY3Rpb24tTWVtYmVycyBDb21wb3NpdGlvbgoKQSBjb2xsZWN0aW9uLW1lbWJlciBjb21wb3NpdGlvbiB3aGVyZSBwYXJ0cyBhcmUgcGVybWFuZW50bHkgZnVzZWQgdG8gdGhlIHdob2xlIGFuZCB0aGVyZSdzIGFuIG9yZGVyaW5nIHRvIHRoZSBwYXJ0cy4gRm9yIGV4YW1wbGUsIGEgd2Vla2x5IHRpbWUgc2hlZXQgY29uc2lzdHMgb2YgZGFpbHkgdGltZSBzaGVldHMgb3IgYSBmbGlnaHQgcmVzZXJ2YXRpb24gY29uc2lzdHMgb2YgZmxpZ2h0IHNlZ21lbnQgcmVzZXJ2YXRpb25zLgoKIyMgQ29uY2x1c2lvbiB7I2NvbmNsfQoKT24gbWFueSBvY2Nhc2lvbnMgc29tZSByZWxhdGlvbnNoaXAgY2FuIGJlIHZpZXdlZCBhcyBmYWxsaW5nIGludG8gbW9yZSB0aGFuIG9uZSBwYXR0ZXJuIC0tIHRoZSBwcmVjaXNlIHBhdHRlcm4gY2xhc3NpZmljYXRpb24gZG9lcyBub3QgbWF0dGVyLiBUaGUgcHVycG9zZSBvZiB0aGUgcGF0dGVybnMgaXMgdG8gcHJlc2VudCB2YXJpb3VzIHNpdHVhdGlvbnMgd2hlcmUgYW4gYW5hbHlzdCBtaWdodCBkaXNjb3ZlciBhZ2dyZWdhdGlvbnMgb3IgY29tcG9zaXRpb25zIHJhdGhlciB0aGFuIHNpbXBsZSBhc3NvY2lhdGlvbnMuIFdoZW4gaXMgZG91YnQsIG1ha2UgdGhlIHJlbGF0aW9uc2hpcCBhbiBhc3NvY2lhdGlvbiAtLSBpdCBjYW4gYWx3YXlzIGJlIHJlZmluZWQgaW50byBhbiBhZ2dyZWdhdGlvbiBvciBhIGNvbXBvc2l0aW9uIHdoZW4gYWRkaXRpb25hbCBjb25zdHJhaW50cyBhcmUgZGlzY292ZXJlZC4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMgRmlsZXMgJiBSZXNvdXJjZXMKCmBgYHtyIHppcEZpbGVzLCBlY2hvPUZBTFNFfQp6aXBOYW1lID0gc3ByaW50ZigiTGVzc29uRmlsZXMtJXMtJXMuemlwIiwgCiAgICAgICAgICAgICAgICAgcGFyYW1zJGNhdGVnb3J5LAogICAgICAgICAgICAgICAgIHBhcmFtcyRudW1iZXIpCgp0ZXh0QUxpbmsgPSBwYXN0ZTAoIkFsbCBGaWxlcyBmb3IgTGVzc29uICIsIAogICAgICAgICAgICAgICBwYXJhbXMkY2F0ZWdvcnksIi4iLHBhcmFtcyRudW1iZXIpCgojIGRvd25sb2FkRmlsZXNMaW5rKCkgaXMgaW5jbHVkZWQgZnJvbSBfaW5zZXJ0MkRCLlIKa25pdHI6OnJhd19odG1sKGRvd25sb2FkRmlsZXNMaW5rKCIuIiwgemlwTmFtZSwgdGV4dEFMaW5rKSkKYGBgCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIFJlZmVyZW5jZXMKCi0gICBbVmlzdWFsIFBhcmFkaWdtIChuZCkuIFVNTCBBc3NvY2lhdGlvbiB2cyBBZ2dyZWdhdGlvbiB2cyBDb21wb3NpdGlvbl0oaHR0cHM6Ly93d3cudmlzdWFsLXBhcmFkaWdtLmNvbS9ndWlkZS91bWwtdW5pZmllZC1tb2RlbGluZy1sYW5ndWFnZS91bWwtYWdncmVnYXRpb24tdnMtY29tcG9zaXRpb24vKQoKIyMgRGlhZ3JhbSBTb3VyY2VzCgotICAgW0x1Y2lkQ2hhcnQgRGlhZ3JhbTogVHV0b3JpYWxdKGh0dHBzOi8vbHVjaWQuYXBwL2x1Y2lkY2hhcnQvYTcwMDQyMzItMzJmNy00NmRjLWFhNDktOTA3NzE0ZWJiYTRhL2VkaXQ/dmlld3BvcnRfbG9jPTE1NyUyQzY5JTJDMTYxNiUyQzExNDMlMkMwXzAmaW52aXRhdGlvbklkPWludl9jY2JjODA5OS0zYzRkLTRjYjEtOGQyYS1lYjhlZDMxYWI5NjEpCgotICAgW0x1Y2lkQ2hhcnQgRGlhZ3JhbTogVU1MIFBhdHRlcm5zXShodHRwczovL2x1Y2lkLmFwcC9sdWNpZGNoYXJ0LzEzNTdlZGY5LTUzNGYtNGFiZi05NTUwLWJmODcxOWVmYmI1Ny9lZGl0P3ZpZXdwb3J0X2xvYz0xMTIlMkMtMzglMkMxMzAzJTJDMTAwMSUyQzBfMCZpbnZpdGF0aW9uSWQ9aW52X2NhYjVhNWI3LTZhY2EtNGIxNy04ZDQ5LWQzNDM1Nzk2ODVmMSkKCiMjIEVycmF0YQoKW0xldCB1cyBrbm93XShodHRwczovL2Zvcm0uam90Zm9ybS5jb20vMjEyMTg3MDcyNzg0MTU3KXt0YXJnZXQ9Il9ibGFuayJ9Lgo=