npm package: @schematize/metamodel
Description: Schematize Metamodel Library
Author: Benjamin Bytheway
Latest version: 0.6.3


# Metamodel

@schematize/metamodel is a javascript implementation of the "UML Metamodel".

## UML

Let's first talk about the "UML" in UML Metamodel.

UML stands for "Unified Modeling Language".  UML is an international standard managed by [the Object Management Group (OMG)](https://www.omg.org).  UML has also been published by the International Organization for Standardization (ISO) and the International Electrotechnical Commission (IEC) as the ISO/IEC 19501 standard. (See [ISO/IEC 19505-1:2012](https://www.iso.org/standard/32624.html))

> "The objective of UML is to provide system architects, software engineers, and software developers with tools for analysis, design, and implementation of software-based systems as well as for modeling business and similar processes."
> - <cite>[UML 2.5.1 Specification Section 1](https://www.omg.org/spec/UML/2.5.1/PDF)</cite>

In short, UML is a modeling language standard for describing systems and processes.

## Metamodel

Okay, what about the "Metamodel" portion of UML Metamodel?

The prefix "meta" usually means "about itself" or "above" or "beyond".  You may have heard the phrase "Metadata is data about data" or "data that describes data".  Well, a Metamodel is a model of models.  

To put it all together.  The UML Metamodel is a model for modeling models.  To take it full circle, since the UML Metamodel is a model, it models itself. 🤯  Inception!

This library uses and implements the UML Metamodel described here: https://www.omg.org/spec/UML/2.5.1.

## Side-note

Schemas and Models are a core concept of systems architecture, and a rock-solid stable foundation upon which to build everything.  Schematizing something is the act or process of reducing to a schema or model.  Hence the reason behind the name name "Schematize". 😉  It all started here.

## Features

- Ability to model models

- Classical and/or Prototypal inheritance pattern support

- OOP and/or Functional programming patterns

- Performance

- No external dependencies (only 2 @schematize dependencies)

- Cross-platform.
  - Modern Browsers (Chrome, Safari, Firefox, Edge)
  - Node
  - Deno

- Semantic mapping of API names to real programming concepts (Class really means Class, etc.)

```javascript 
typeof (new Metamodel.StructuredClassifiers.Class()) === 'function';
```

- Inheritance works through prototypal inheritance just as it does in plain javascript.

```javascript 
const Class = Metamodel.StructuredClassifiers.Class;
class MyClass extends Class.prototype {}
const instance = new MyClass();
console.log(instance instanceof MyClass); // true
console.log(instance instanceof Class.prototype); // true
```

- `instanceof` works the same as it would in plain javascript. 

```javascript 
(new MyClass() instanceof MyClass) === true;
```

- Supports composition while also supporting inheritance.  Pick whatever style fits the job.

```javascript
const Class = Metamodel.StructuredClassifiers.Class;
const Interface = Metamodel.SimpleClassifiers.Interface;

// Inheritance
const Person = new Class({
  name: 'Person'
});
const Employee = new Class({
  name: 'Employee',
  generalization: [{ general: Person }]  // extends Person
});
const employee = new Employee({ name: 'Ben' });
console.log(employee instanceof Employee); // true
console.log(employee instanceof Person); // true

// Composition
const ICanFly = new Interface({
  name: 'ICanFly',
});
const ICanSwim = new Interface({
  name: 'ICanSwim',
});
const Penguin = new Class({
  name: 'Penguin',
  interfaceRealization: [{ contract: ICanSwim}]
});
const Parrot = new Class({
  name: 'Parrot',
  interfaceRealization: [{ contract: ICanFly}]
});
const Duck = new Class({
  name: 'Duck',
  interfaceRealization: [{ contract: ICanFly }, { contract: ICanSwim}]
});
const penguin = new Penguin({});
const parrot = new Parrot({});
const duck = new Duck({});
console.log(penguin instanceof ICanFly); // false
console.log(penguin instanceof ICanSwim); // true
console.log(parrot instanceof ICanFly); // true
console.log(parrot instanceof ICanSwim); // false
console.log(duck instanceof ICanFly); // true
console.log(duck instanceof ICanSwim); // true
```

- Types (Classes, Interfaces, DataTypes, Enumerations, etc.) as well as their respective instances can all be created with or without the `new` keyword. 

```javascript 
// with new
const MyClass = new Metamodel.StructuredClassifiers.Class();
// without new
const MyClass = Metamodel.StructuredClassifiers.Class();
```

- Types (Classes, Interfaces, DataTypes, Enumerations, etc.) are first class citizens and can be treated as objects, instances, or types in their respective contexts.

```javascript 
const MyClass = new Metamodel.StructuredClassifiers.Class();
// acting as an instance of Metamodel.StructuredClassifiers.Class
MyClass.property = 'object context';
// acting as a class that can create instances
const instance = MyClass({});
```

- Built on top of @schematize/instance.js Allows ability to hook into events and take further action (saving or updating state, persisting, doing additional logic)

```javascript
const MyClass = new Metamodel.StructuredClassifiers.Class();
const instance = new MyClass({});
instance.on('set', (evt) => {
  console.log(evt.detail.property + ':' + evt.detail.value);
});
instance.set('name', 'theValue'); // logs: 'name:theValue'
```

- Allows the ability to mimic core library behavior at the meta level.

```javascript
const ClassCreator = new Metamodel.StructuredClassifiers.Class({
  name: 'ClassCreator',
  metaclass: 'Class'
});
const AnotherClass = new ClassCreator({
  name: 'AnotherClass',
});
const instance = new AnotherClass({});
```

- Exposes the ability to extend functionality in whatever way makes most sense, either through extending prototypes or by adding event listening functionality.

```javascript 
// Extension by prototype inheritance
Class.prototype.save = function () {
  // implement code here that all Class instances will inherit.
}

// Extension by event listeners
Class.prototype.on('set', (evt) => {
  // implement code that does something here
});
```

- Implements EventTarget Interface as well as other common patters for listening to and firing events. (More details below)

```javascript 
instance.addEventListener('set', (evt) => {
  // evt.detail
});
```

- Feels like you are using plain javascript Functions, Classes, and Objects.  No strange patters of creating instances, class extension, etc. that are not already native patterns in Javascript.

```javascript 

// Classes and Functions in Plain JS
class JSClass {
}
function JSFunctionConstructor() {
}

// Classes and Functions in Schematize.js
const MetamodelClass = Metamodel.StructuredClassifiers.Class({
  name: 'MetamodelClass'
});

// Objects in Plain JS
let jsClassInstance = new JSClass();
let jsFunctionInstance = new JSFunction();
jsClassInstance.property = 'value';

// Objects in Schematize.js
let schematizeInstance = new MetamodelClass();
schematizeInstance.property = 'value';

```

- Schematize.js plays nicely with plain javascript Functions, Classes, and Objects.  You aren't locked into all one or the other.

```javascript 
// use your native JS Class and extend a class build from Schematize.js.
const MetamodelClass = Metamodel.StructuredClassifiers.Class({
  name: 'MetamodelClass'
});
class JSClass extends MetamodelClass {}
let instance = new JSClass();
instance instanceof MetamodelClass; // true
```

- Ability to automatically handle any of these types of associations: 
  - one-to-one (1..1)
  - one-to-many (1..\*)
  - many-to-many (\*..\*)
  - and any other variation of those and variation in multiplicity upper or lower values. (0..1, 0..\*, 2..2, 2..\*, etc.)

- Automatic "magic" handling of opposite ends of an association.

```javascript
// assuming there is a one-to-many Association between Employee and Assignment
// Employee [1] <==> [*] Assignment
const employee = new Employee();
const assignment1 = new Assignment();
// (assuming proxies, but can use .set function and will work as well)
assignment1.employee = employee;
// employee.assignments Collection now automatically contains the assignment
// without explicit assignment
const assignment2 = new Assignment();
employee.assignments.push(assignment2);
// assignment2.employee now automatically contains the employee without explicit
// assignment
```

- Automatic "linking" of instances by simply creating an instance of an Association (or a link):

```javascript
// assuming the above model with this association definition (not complete):
let A_employee_assignment = new Association({
  memberEnds: [{
    __id__: 'PROPERTY_EMPLOYEE_ABC',
    class: Assignment,
    name: 'employee',
    type: Employee,
    lowerValue: new UnlimitedNatural(1),
    upperValue: new UnlimitedNatural(1)  // 0..*
  }, {
    __id__: 'PROPERTY_ASSIGNMENTS_DEF',
    class: Employee,
    name: 'assignments',
    type: Assignment,
    lowerValue: new UnlimitedNatural(0),
    upperValue: new UnlimitedNatural('*')  // 0..*
  }]
});
// ...
let employee = Employee({ __id__: 'EMPLOYEE_123' });
let assignment = Assignment({ __id__: 'ASSIGNMENT_456' });
// creating an instance of the Association (or generally what's referred to as 
// a "link") automatically assigns them together
new A_employee_assignment({
  PROPERTY_EMPLOYEE_ABC: 'EMPLOYEE_123',
  PROPERTY_ASSIGNMENTS_DEF: 'ASSIGNMENT_456',
});
// employee.assignments Collection now automatically contains the assignment
// without explicit assignment
// assignment.employee also automatically is set to the employee instance 
```

- (along the same lines) Bi-directional reference support for traversing both directions of an association/relationship between instances.

- Automatic coersion attempts based on the property types. 

- Automatic type checking and validation

- Ability to serialize an entire model to JSON, store it, and then later "resurrect" it back into existence dynamically to be able to continue to create instances, links, etc.

- Just as Instance.js allows, automatic "magical" handling of all of the above functionality when using plain object access, assignment, or deletion just like you would with plain objects or arrays.

## Dependencies

- `@schematize/instance.js`: Core instance management
- `@schematize/refs`: JavaScript reference implementations

## Installation

```bash
npm install @schematize/metamodel
```

## Usage

### Include script

Start by including the script that suits your needs and environment:

#### Browser global

```html
<script src="node_modules/@schematize/metamodel/dist/iife/Metamodel.min.js"></script>
<script>console.log(Metamodel);</script>
```

#### Browser module 

```javascript
import Metamodel from 'node_modules/@schematize/metamodel/dist/es/Metamodel.min.js';
```

#### Node require

```javascript
const Metamodel = require('@schematize/metamodel');
```

#### Node module

```javascript
import Metamodel from '@schematize/metamodel';
```

### Full UML Metamodel Functionality

From there, you will need to "resurrect" a UML model into existence (basically hydrate it) using a interchange JSON file or string.  For this you can check out the `@schematize/model-json` repository.  Here is an example:

```javascript
// For Metamodel to work, you must use at bare-minimum UML and PrimitiveTypes
import {
  jsonUML,
  jsonPrimitiveTypes
} from '@schematize/model-json';

// Resurrect a UML metamodel from JSON
const [
  UML,
  PrimitiveTypes
] = Metamodel.resurrect(
  jsonUML,
  jsonPrimitiveTypes
);

// optionally assign Metamodel Core properties to the UML object
Object.assign(UML, Metamodel);
// UML is the Metamodel
Metamodel = UML;

// Access metamodel elements through the UML Metamodel package
const Class = Metamodel.StructuredClassifiers.Class;
const Association = Metamodel.StructuredClassifiers.Association;
const Property = Metamodel.Classification.Property;
const Package = Metamodel.Packages.Package;
```

What's cool about this is it also means that you can pass your own custom UML model json interchange if you wish.  As long as it adheres to the core UML Metamodel, your modifed Metamodel will be "resurrected" into existence and contain all of your modifications.  Meta-meta-meta programming. 😱

### Essential Functionality only

If you are only interested in the essential functionality of the Metamodel library without the UML Metamodel, instead of  `import Metamodel` you only need to import `Essential` from `src/Essential.mjs`.

```javascript
// This will set up all of the essential Metamodel event listeners, and add 
// functionality to Instance.prototype, Collection.prototype, etc.  Even if
// you are not using Essential directly, this call is still necessary.
import * as Essential from '@schematize/metamodel/src/Essential.mjs';
import Class_prototype from '@schematize/metamodel/src/Class/prototype.mjs';

// build your model using regular ES5 function constructors or ES6 classes
class MyClass extends Class_prototype {
  constructor(properties = {}) {
    properties.__type__ = MyClass;
    return super(properties);
  }
  static get ownedAttribute () {
    return [{
      class: MyClass,
      name: `myStringProperty`,
      type: String,
    }, {
      class: MyClass,
      name: `myBooleanProperty`,
      type: Number,
    }];
  }
}

// use your model
let instance = MyClass();
```

This is very useful and also performance optimized.  

⚠️ The rest of this documentation assumes you are using the "Full UML Metamodel Functionality".

### Create a new Class

There are 2 ways to create a new Class:

#### 1) Instantiate a new Metamodel Class

```javascript
const Class = Metamodel.StructuredClassifiers.Class;
const Association = Metamodel.StructuredClassifiers.Association;

let 
  Account,
  Transaction;

Account = new Class({
  name: 'Account',
  ownedAttribute: [{
    id: 2,
    name: 'accountNumber',
    type: Number,
  }, {
    name: 'name',
    type: String,
  }, {
    name: 'active',
    type: Boolean,
  }, {
    // Account has 0 to * (many) of the type "Transaction" which form the 
    // association "Account has many Transactions"
    name: 'transactions',
    type: Transaction,
    lowerValue: 0,
    upperValue: Infinity,
    association: {
      id: 3,
      name: 'Account has many Transactions'
    }
  }],
});

Transaction = new Class({
  name: 'Transaction',
  ownedAttribute: [{
    name: 'accountNumber',
    type: Number,
  }, {
    name: 'date',
    type: Date,
  }, {
    // Transaction has a min of 1 to a max of 1 of the type "Account" which 
    // form the association "Account has many Transactions"
    name: 'account',
    type: Account,
    lowerValue: 1,
    upperValue: 1,
    association: {
      id: 3,
    }
  }],
});

// an account instance
const account = new Account({
  accountNumber: 1594905,
  name: 'first thing',
  active: true,
});

// a trasnaction instance
const transaction = new Transaction({
  accountNumber: 1594905,
  date: new Date('2019-03-15 12:13:03')
});

```

#### 2) Point your Class's prototype chain at Metamodel.StructuredClassifiers.Class.prototype

```javascript
const Class = Metamodel.StructuredClassifiers.Class;
const Association = Metamodel.StructuredClassifiers.Association;

const A_account_transaction = function A_account_transaction (properties = {}) {
  properties.__type__ = properties.__type__ || A_account_transaction;
  return Association.prototype(properties, this);
};
A_account_transaction.prototype = Object.create(Association.prototype.prototype);
A_account_transaction.prototype.constructor = A_account_transaction;

//--------------------------------------------
// You can do this by using ES5 class syntax:

const Account = function Account (properties) {
  // explicitly set type 
  properties.__type__ = Account;
  return Class.prototype(properties, this);
};
Account.prototype = Object.create(Class.prototype.prototype);
Account.prototype.constructor = Account;

Account.ownedAttribute = [{
  class: Account,
  name: 'accountNumber',
  type: Number,
}, {
  class: Account,
  name: 'name',
  type: String,
}, {
  class: Account,
  name: 'active',
  type: Boolean
}, {
  class: Account,
  // transactions
  name: 'transactions',
  // type
  type: Transaction,
  // has 0
  lowerValue: 0,
  // to many
  upperValue: Infinity,
  // to form this relationships
  association: AccountTransactionAssociation,
}];

//-----------------------------------------------
// Or you can do this by using ES6 class syntax:

class Transaction extends Schematize.Class.prototype {

  constructor(properties) {
    properties.__type__ = Transaction;
    return super(properties);
  }

  static get ownedAttributes () {
    return [
      {
        class: Transaction,
        name: 'accountNumber',
        type: Number,
      },
      {
        class: Transaction,
        name: 'date',
        type: Date,
      }, 
      {
        // this class
        class: Transaction,
        // account
        name: 'account',
        // type
        type: Account,
        // belongs to 1 (required to be tied to at least 1)
        lowerValue: 1,
        // to maximum of 1
        upperValue: 1,
        // to form this relationships
        association: AccountTransactionAssociation,
      }
    ];
  }

}

A_account_transaction.memberEnd = [
  Account.ownedAttribute[2],
  Transaction.ownedAttribute[2]
];

const account = new Account({
  accountNumber: 1594905,
  name: 'Account Name',
  active: true,
});

const transaction = new Transaction({
  accountNumber: 1594905,
  date: new Date('2019-03-15 12:13:03')
});
```

## @schematize/instance.js

The Schematize Metamodel library is built on top of the Schematize Instance.js library.  Instance is the base class for all Classes and instances built with Metamodel.  It therefore inherits all of the same functionality and is built on the same principles.  Also, fun fact, `Metamodel.StructuredClassifiers.Class.prototype.prototype` IS `Instance.prototype` (described later).

Please see the README.md documentation there (https://www.npmjs.com/package/@schematize/instance.js) for the following: 

- `__type__` the "type" of an instance...closely relates to the Metamodel.CommonStructure.Type Metaclass.
- `__id__` the unique identifier given to every instance
- `EventTarget` and it's corresponding methods: `addEventListener`, `removeEventListener`, `dispatchEvent`
- `__dispatch__` and how to configure event capturing/bubbling/propogation.
- `Instance` the core base constructor function and the events it dispatches when creating instances:
  - `beforeInstance` - event fired before any instance gets fully instantiated
  - `instance` - after an instance is created, but before property assignment
- `Instance.prototype` methods which are inherited by all instances in Metamodel including: 
  - `get` - getting a value from a property of an instance
  - `set` - setting a value to a property of an instance
  - `deleteProperty` - deleting a property of an instance
  - `defineProperty` - defining a property on an instance (using standard Javascript descriptor syntax)
  - `assign` - assigning values to multiple properties of an instance
  - `destroy` - destroying an instance
- `Instance Cache` - the way single instances are kept and referenced everywhere
- `Backrefs` - the way deferred reference resolution works
- `Proxies` - internally how you can make simple operations like assigning, accessing, or deleting properties "magic" where they automatically trigger events and other functionality.
- `Collections` - An extension of native Arrays that can be observed, listened to, extended, and even proxied
- `Collection.prototype` methods which are used extensively in this library and for triggering change detection and other extended use cases:
  - `Collection.prototype.append` - same as `Array.prototype.push`, but better
  - `Collection.prototype.prepend` - same as `Array.prototype.unshift`, but better
  - `Collection.prototype.removeLast` - same as `Array.prototype.pop`, but better
  - `Collection.prototype.removeFirst` - same as `Array.prototype.shift`, but better
  - `Collection.prototype.replace` - same as `Array.prototype.splice`, but better
  - `Collection.prototype.flip` - same as `Array.prototype.reverse`, but better
  - `Collection.prototype.order` - same as `Array.prototype.sort`, but better

## Metamodel Functionality

TODO: Auto-setting of the opposite
TODO: Auto-linking via Associations
TODO: etc.

## Prototype Structure

### Metamodel Javascript Prototype Structure

I feel it is very important to explain how the prototype model works.  This will help you understand in more depth how inheritance works and lay the foundation for how to inherit, extend, of manipulate the library as you see fit.  

The built-in javascript objects inherit according to this diagram.

![Javascript Prototype Model](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEwNTAiIGhlaWdodD0iNDI1IiA+IDxzdHlsZT4gc3ZnIHsgZm9udC1mYW1pbHk6IEFyaWFsLCBIZWx2ZXRpY2EsIHNhbnMtc2VyaWY7IH0gLmxlZ2VuZCByZWN0IHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDM7IGZpbGw6IHRyYW5zcGFyZW50OyB9IC5wcm90by1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IH0gLmNvbnN0cnVjdG9yLWxpbmUgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMiwgMjsgfSAuZ2VuZXJhbC1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDUsIDU7IH0gLmZ1bmN0aW9uIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDM7IH0gLm9iamVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyB9IC5ibGFjay1ib3JkZXIgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMzsgfSA8L3N0eWxlPiA8ZGVmcz4gPG1hcmtlciBpZD0icHJvdG8tYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjciIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWdvbiBwb2ludHM9IjEgMSwgOSA0LCAxIDciIGZpbGw9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSIxIiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlsaW5lIHBvaW50cz0iOSAxLCAxIDQsIDkgNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiAvPiA8L21hcmtlcj4gPG1hcmtlciBpZD0iY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjgiIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWxpbmUgcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSJub25lIiBzdHJva2U9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJnZW5lcmFsLWFycm93aGVhZC1lbmQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSI3IiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlnb24gcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSIjNjY2IiAvPiA8L21hcmtlcj4gPGxpbmVhckdyYWRpZW50IGlkPSJmdW5jdGlvbi1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoNjIsIDIwMCwgMjU1KTtzdG9wLW9wYWNpdHk6MSIgLz4gPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMCwgMTI3LCAyMzEpO3N0b3Atb3BhY2l0eToxIiAvPiA8L2xpbmVhckdyYWRpZW50PiA8bGluZWFyR3JhZGllbnQgaWQ9Im9iamVjdC1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMjU1LCAyNDAsIDEwNyk7c3RvcC1vcGFjaXR5OjEiIC8+IDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDIzMSwgMTMxLCAwKTtzdG9wLW9wYWNpdHk6MSIgLz4gPC9saW5lYXJHcmFkaWVudD4gPC9kZWZzPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMTApIiBjbGFzcz0ibGVnZW5kIiA+IDxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTI1IiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMjUiIGZpbGw9IiM2NjYiID5MZWdlbmQ8L3RleHQ+IDxsaW5lIHgxPSIxNSIgeTE9IjQ3IiB4Mj0iNzUiIHkyPSI0NyIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDx0ZXh0IHg9IjEwMCIgeT0iNTAiIGZpbGw9IiM2NjYiID4uX19wcm90b19fPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI3MiIgeDI9Ijc1IiB5Mj0iNzIiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSI3NSIgZmlsbD0iIzY2NiIgPi5wcm90b3R5cGUvLmNvbnN0cnVjdG9yPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI5NyIgeDI9Ijc1IiB5Mj0iOTciIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSIxMDAiIGZpbGw9IiM2NjYiID4uZ2VuZXJhbGl6YXRpb24uZ2VuZXJhbDwvdGV4dD4gPC9nPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMjUwKSI+IDwhLS0gRnVuY3Rpb24ucHJvdG90eXBlIC0+IE9iamVjdC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSIxMDAiIHgyPSIzNzUiIHkyPSI1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gRnVuY3Rpb24gLT4gRnVuY3Rpb24ucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNzUwIiB5MT0iMTEwIiB4Mj0iNTAwIiB5Mj0iMTEwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBPYmplY3QgPD0+IE9iamVjdC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI1MDAiIHkxPSIyNSIgeDI9Ijc1MCIgeTI9IjI1IiBjbGFzcz0iY29uc3RydWN0b3ItbGluZSIgbWFya2VyLXN0YXJ0PSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1zdGFydCkiIG1hcmtlci1lbmQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCkiID48L2xpbmU+IDwhLS0gT2JqZWN0IC0+IEZ1bmN0aW9uLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1MCIgeTE9IjQ1IiB4Mj0iNTAwIiB5Mj0iMTEwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBPYmplY3QucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPk9iamVjdC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBPYmplY3QgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0iZnVuY3Rpb24iIGZpbGw9InVybCgjZnVuY3Rpb24tYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPk9iamVjdDwvdGV4dD4gPC9nPiA8IS0tIEZ1bmN0aW9uIDw9PiBGdW5jdGlvbi5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI1MDAiIHkxPSIxMjUiIHgyPSI3NTAiIHkyPSIxMjUiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgPjwvbGluZT4gPCEtLSBGdW5jdGlvbi5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgMTAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+RnVuY3Rpb24ucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gRnVuY3Rpb24gLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgMTAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+RnVuY3Rpb248L3RleHQ+IDwvZz4gPC9nPiA8L3N2Zz4=)

Please note that Function.prototype is actually a "function" type:

```javascript
typeof Function.prototype; // "function"
typeof Object.prototype; // "object"
```

If you run this is any javascript environment (node, browser, etc.) you should see the following:

```javascript
Object.getPrototypeOf(Function) === Function.prototype; // true
Function.__proto__ === Function.prototype; // true (same as above)

Object.getPrototypeOf(Object) === Function.prototype; // true
Object.__proto__ === Function.prototype; // true (same as above)

Object.getPrototypeOf(Function.prototype) === Object.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true (same as above)
```

The beauty of this structure is that `Object` and `Function` are both instances of themselves.

```javascript 
Object instanceof Function; // true
Function instanceof Function; // true
Object instanceof Object; // true
Function instanceof Object; // true
```

The UML Metamodel prototype model is similar.

![Metamodel Prototype Model](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjE1MDAiIGhlaWdodD0iMTIwMCIgPiA8c3R5bGU+IHN2ZyB7IGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOyB9IC5sZWdlbmQgcmVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyBmaWxsOiBub25lOyB9IC5wcm90by1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IGZpbGw6IG5vbmU7IH0gLmNvbnN0cnVjdG9yLWxpbmUgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMiwgMjsgZmlsbDogbm9uZTsgfSAuZ2VuZXJhbC1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDUsIDU7IGZpbGw6IG5vbmU7IH0gLmZ1bmN0aW9uIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDM7IH0gLm9iamVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyB9IC5ibGFjay1ib3JkZXIgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMzsgfSA8L3N0eWxlPiA8ZGVmcz4gPG1hcmtlciBpZD0icHJvdG8tYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjciIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWdvbiBwb2ludHM9IjEgMSwgOSA0LCAxIDciIGZpbGw9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSIxIiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlsaW5lIHBvaW50cz0iOSAxLCAxIDQsIDkgNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiAvPiA8L21hcmtlcj4gPG1hcmtlciBpZD0iY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjgiIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWxpbmUgcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSJub25lIiBzdHJva2U9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJnZW5lcmFsLWFycm93aGVhZC1lbmQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSI3IiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlnb24gcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSIjNjY2IiAvPiA8L21hcmtlcj4gPGxpbmVhckdyYWRpZW50IGlkPSJmdW5jdGlvbi1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoNjIsIDIwMCwgMjU1KTtzdG9wLW9wYWNpdHk6MSIgLz4gPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMCwgMTI3LCAyMzEpO3N0b3Atb3BhY2l0eToxIiAvPiA8L2xpbmVhckdyYWRpZW50PiA8bGluZWFyR3JhZGllbnQgaWQ9Im9iamVjdC1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMjU1LCAyNDAsIDEwNyk7c3RvcC1vcGFjaXR5OjEiIC8+IDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDIzMSwgMTMxLCAwKTtzdG9wLW9wYWNpdHk6MSIgLz4gPC9saW5lYXJHcmFkaWVudD4gPC9kZWZzPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMTApIiBjbGFzcz0ibGVnZW5kIiA+IDxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTI1IiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMjUiIGZpbGw9IiM2NjYiID5MZWdlbmQ8L3RleHQ+IDxsaW5lIHgxPSIxNSIgeTE9IjQ3IiB4Mj0iNzUiIHkyPSI0NyIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDx0ZXh0IHg9IjEwMCIgeT0iNTAiIGZpbGw9IiM2NjYiID4uX19wcm90b19fPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI3MiIgeDI9Ijc1IiB5Mj0iNzIiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSI3NSIgZmlsbD0iIzY2NiIgPi5wcm90b3R5cGUvLmNvbnN0cnVjdG9yPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI5NyIgeDI9Ijc1IiB5Mj0iOTciIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSIxMDAiIGZpbGw9IiM2NjYiID4uZ2VuZXJhbGl6YXRpb24uZ2VuZXJhbDwvdGV4dD4gPC9nPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMjUwKSI+IDwhLS0gT2JqZWN0LnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLCAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5PYmplY3QucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gSW5zdGFuY2UucHJvdG90eXBlIC0+IE9iamVjdC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSIxMDAiIHgyPSIzNzUiIHkyPSI1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gSW5zdGFuY2UucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDEwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+SW5zdGFuY2UucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gSW5zdGFuY2UgLT4gSW5zdGFuY2UucHJvdG90eXBlIC0tPiA8cGF0aCBkPSJNIDI1MCA3MjUgQyAxMDAgNzI1LCAxMDAgMTI1LCAyNTAgMTI1IiBjbGFzcz0iY29uc3RydWN0b3ItbGluZSIgbWFya2VyLW5vdC1zdGFydD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQpIiBtYXJrZXItZW5kPSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIEluc3RhbmNlIDw9PiBJbnN0YW5jZS5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI1MDAiIHkxPSIxMjUiIHgyPSI3NTAiIHkyPSIxMjUiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgPjwvbGluZT4gPCEtLSBJbnN0YW5jZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzUwLCAxMDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9ImZ1bmN0aW9uIiBmaWxsPSJ1cmwoI2Z1bmN0aW9uLWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5JbnN0YW5jZTwvdGV4dD4gPC9nPiA8IS0tIEVsZW1lbnQucHJvdG90eXBlIC0+IEluc3RhbmNlLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjIwMCIgeDI9IjM3NSIgeTI9IjE1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gRWxlbWVudCAtPiBDbGFzcy5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI3NTAiIHkxPSIyNDAiIHgyPSI1MDAiIHkyPSI3MTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIEVsZW1lbnQgPD0+IEVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNTAwIiB5MT0iMjI1IiB4Mj0iNzUwIiB5Mj0iMjI1IiBjbGFzcz0iY29uc3RydWN0b3ItbGluZSIgbWFya2VyLXN0YXJ0PSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1zdGFydCkiIG1hcmtlci1lbmQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCkiID48L2xpbmU+IDwhLS0gRWxlbWVudC5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgMjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5FbGVtZW50LnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIEVsZW1lbnQgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgMjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+RWxlbWVudDwvdGV4dD4gPC9nPiA8IS0tIE5hbWVkRWxlbWVudC5wcm90b3R5cGUgLT4gRWxlbWVudC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSIzMDAiIHgyPSIzNzUiIHkyPSIyNTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIE5hbWVkRWxlbWVudCAtPiBFbGVtZW50IC0tPiA8bGluZSB4MT0iODc1IiB5MT0iMzAwIiB4Mj0iODc1IiB5Mj0iMjUwIiBjbGFzcz0iZ2VuZXJhbC1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI2dlbmVyYWwtYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gTmFtZWRFbGVtZW50IC0+IENsYXNzLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1MCIgeTE9IjM0MCIgeDI9IjUwMCIgeTI9IjcxMCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gTmFtZWRFbGVtZW50IDw9PiBOYW1lZEVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNTAwIiB5MT0iMzI1IiB4Mj0iNzUwIiB5Mj0iMzI1IiBjbGFzcz0iY29uc3RydWN0b3ItbGluZSIgbWFya2VyLXN0YXJ0PSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1zdGFydCkiIG1hcmtlci1lbmQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCkiID48L2xpbmU+IDwhLS0gTmFtZWRFbGVtZW50LnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLCAzMDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPk5hbWVkRWxlbWVudC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBOYW1lZEVsZW1lbnQgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgMzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+TmFtZWRFbGVtZW50PC90ZXh0PiA8L2c+IDwhLS0gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtPiBOYW1lZEVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iMzc1IiB5MT0iNDAwIiB4Mj0iMzc1IiB5Mj0iMzUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBQYWNrYWdlYWJsZUVsZW1lbnQgLT4gTmFtZWRFbGVtZW50IC0tPiA8bGluZSB4MT0iODc1IiB5MT0iNDAwIiB4Mj0iODc1IiB5Mj0iMzUwIiBjbGFzcz0iZ2VuZXJhbC1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI2dlbmVyYWwtYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gUGFja2FnZWFibGVFbGVtZW50IC0+IENsYXNzLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1MCIgeTE9IjQ0MCIgeDI9IjUwMCIgeTI9IjcxMCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gUGFja2FnZWFibGVFbGVtZW50IDw9PiBQYWNrYWdlYWJsZUVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNTAwIiB5MT0iNDI1IiB4Mj0iNzUwIiB5Mj0iNDI1IiBjbGFzcz0iY29uc3RydWN0b3ItbGluZSIgbWFya2VyLXN0YXJ0PSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1zdGFydCkiIG1hcmtlci1lbmQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCkiID48L2xpbmU+IDwhLS0gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLCA0MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPlBhY2thZ2VhYmxlRWxlbWVudC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBQYWNrYWdlYWJsZUVsZW1lbnQgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgNDAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+UGFja2FnZWFibGVFbGVtZW50PC90ZXh0PiA8L2c+IDwhLS0gVHlwZS5wcm90b3R5cGUgLT4gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjUwMCIgeDI9IjM3NSIgeTI9IjQ1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gVHlwZSAtPiBQYWNrYWdlYWJsZUVsZW1lbnQgLS0+IDxsaW5lIHgxPSI4NzUiIHkxPSI1MDAiIHgyPSI4NzUiIHkyPSI0NTAiIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBUeXBlIC0+IENsYXNzLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1MCIgeTE9IjU0MCIgeDI9IjUwMCIgeTI9IjcxMCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gVHlwZSA8PT4gVHlwZS5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI1MDAiIHkxPSI1MjUiIHgyPSI3NTAiIHkyPSI1MjUiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgPjwvbGluZT4gPCEtLSBUeXBlLnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLCA1MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPlR5cGUucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gVHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNzUwLCA1MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9ImZ1bmN0aW9uIiBmaWxsPSJ1cmwoI2Z1bmN0aW9uLWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5UeXBlPC90ZXh0PiA8L2c+IDwhLS0gQ2xhc3NpZmllci5wcm90b3R5cGUgLT4gVHlwZS5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSI2MDAiIHgyPSIzNzUiIHkyPSI1NTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIENsYXNzaWZpZXIgLT4gVHlwZSAtLT4gPGxpbmUgeDE9Ijg3NSIgeTE9IjYwMCIgeDI9Ijg3NSIgeTI9IjU1MCIgY2xhc3M9ImdlbmVyYWwtbGluZSIgbWFya2VyLWVuZD0idXJsKCNnZW5lcmFsLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIENsYXNzaWZpZXIgLT4gQ2xhc3MucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNzUwIiB5MT0iNjQwIiB4Mj0iNTAwIiB5Mj0iNzEwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBDbGFzc2lmaWVyIDw9PiBDbGFzc2lmaWVyLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjUwMCIgeTE9IjYyNSIgeDI9Ijc1MCIgeTI9IjYyNSIgY2xhc3M9ImNvbnN0cnVjdG9yLWxpbmUiIG1hcmtlci1zdGFydD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQpIiBtYXJrZXItZW5kPSJ1cmwoI2NvbnN0cnVjdG9yLWFycm93aGVhZC1lbmQpIiA+PC9saW5lPiA8IS0tIENsYXNzaWZpZXIucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDYwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+Q2xhc3NpZmllci5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBDbGFzc2lmaWVyIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg3NTAsIDYwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0iZnVuY3Rpb24iIGZpbGw9InVybCgjZnVuY3Rpb24tYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPkNsYXNzaWZpZXI8L3RleHQ+IDwvZz4gPCEtLSBDbGFzcy5wcm90b3R5cGUgLT4gQ2xhc3NpZmllci5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSI3MDAiIHgyPSIzNzUiIHkyPSI2NTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIENsYXNzIC0+IENsYXNzaWZpZXIgLS0+IDxsaW5lIHgxPSI4NzUiIHkxPSI3MDAiIHgyPSI4NzUiIHkyPSI2NTAiIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBDbGFzcyAtPiBDbGFzcy5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI3NTAiIHkxPSI3MTAiIHgyPSI1MDAiIHkyPSI3MTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIENsYXNzIDw9PiBDbGFzcy5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI1MDAiIHkxPSI3MjUiIHgyPSI3NTAiIHkyPSI3MjUiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgPjwvbGluZT4gPCEtLSBDbGFzcy5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgNzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+Q2xhc3MucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gQ2xhc3MgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDc1MCwgNzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+Q2xhc3M8L3RleHQ+IDwvZz4gPC9nPiA8L3N2Zz4= "Metamodel Prototype Model")

Note that Class.prototype is also has a type of "function":

```javascript
const Class = Metamodel.StructuredClassifiers.Class;
typeof Class.prototype; // "function"
typeof Object.prototype; // "object"
```

Also note that Class.prototype.prototype is the Instance.prototype, but Instance.prototype.constructor is not Class.prototype.

```javascript
const Class = Metamodel.StructuredClassifiers.Class;
typeof Class.prototype.prototype === Instance.prototype; // true
typeof Instance.prototype.constructor === Class.prototype; // false
```

Okay, so this feels strange right?  Class.prototype.prototpe?  Why two prototypes?

This is because fundamentally to Javascript, whenever you invoke a function constructor with the `new` keyword (or in other words, when you instantiate an instance of a class in javascript), a new object is created which points the `__proto__` at the `.prototype` of the function constructor.

Without being comprehensive, here are a few examples of how the UML Metamodel Classes are similar to the plain built-ins:

```javascript
const Element = Metamodel.CommonStructure.Element;
const Class = Metamodel.StructuredClassifiers.Class;

Object.getPrototypeOf(Element) === Class.prototype; // true
Element.__proto__ === Class.prototype; // true (same as above)

Object.getPrototypeOf(Class) === Class.prototype; // true
Class.__proto__ === Class.prototype; // true (same as above)

// etc.
```

Again, the beauty of this structure is that `Element`, `Class`, etc. are all instances of themselves.

```javascript
const Element = Metamodel.CommonStructure.Element;
const Class = Metamodel.StructuredClassifiers.Class;

Element instanceof Class; // true
Class instanceof Class; // true
Element instanceof Element; // true
Class instanceof Element; // true
```

This is how we acheive the goal of being self-describing, just like UML itself is.

### Prototype Hierarchy

With that foundation, here is prototype hierarchy of some of the most common Classes in the UML Metamodel:

![Metamodel Prototype Hierarchy](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyNTAiIGhlaWdodD0iMTE1MCIgPiA8c3R5bGU+IHN2ZyB7IGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOyB9IC5sZWdlbmQgcmVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyBmaWxsOiBub25lOyB9IC5wcm90by1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IGZpbGw6IG5vbmU7IH0gLmNvbnN0cnVjdG9yLWxpbmUgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMiwgMjsgZmlsbDogbm9uZTsgfSAuZ2VuZXJhbC1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDUsIDU7IGZpbGw6IG5vbmU7IH0gLmZ1bmN0aW9uIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDM7IH0gLm9iamVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyB9IC5ibGFjay1ib3JkZXIgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMzsgfSA8L3N0eWxlPiA8ZGVmcz4gPG1hcmtlciBpZD0icHJvdG8tYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjciIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWdvbiBwb2ludHM9IjEgMSwgOSA0LCAxIDciIGZpbGw9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSIxIiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlsaW5lIHBvaW50cz0iOSAxLCAxIDQsIDkgNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiAvPiA8L21hcmtlcj4gPG1hcmtlciBpZD0iY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjgiIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWxpbmUgcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSJub25lIiBzdHJva2U9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJnZW5lcmFsLWFycm93aGVhZC1lbmQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSI3IiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlnb24gcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSIjNjY2IiAvPiA8L21hcmtlcj4gPGxpbmVhckdyYWRpZW50IGlkPSJmdW5jdGlvbi1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoNjIsIDIwMCwgMjU1KTtzdG9wLW9wYWNpdHk6MSIgLz4gPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMCwgMTI3LCAyMzEpO3N0b3Atb3BhY2l0eToxIiAvPiA8L2xpbmVhckdyYWRpZW50PiA8bGluZWFyR3JhZGllbnQgaWQ9Im9iamVjdC1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMjU1LCAyNDAsIDEwNyk7c3RvcC1vcGFjaXR5OjEiIC8+IDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDIzMSwgMTMxLCAwKTtzdG9wLW9wYWNpdHk6MSIgLz4gPC9saW5lYXJHcmFkaWVudD4gPC9kZWZzPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMTApIiBjbGFzcz0ibGVnZW5kIiA+IDxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTI1IiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMjUiIGZpbGw9IiM2NjYiID5MZWdlbmQ8L3RleHQ+IDxsaW5lIHgxPSIxNSIgeTE9IjQ3IiB4Mj0iNzUiIHkyPSI0NyIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDx0ZXh0IHg9IjEwMCIgeT0iNTAiIGZpbGw9IiM2NjYiID4uX19wcm90b19fPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI3MiIgeDI9Ijc1IiB5Mj0iNzIiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSI3NSIgZmlsbD0iIzY2NiIgPi5wcm90b3R5cGUvLmNvbnN0cnVjdG9yPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI5NyIgeDI9Ijc1IiB5Mj0iOTciIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSIxMDAiIGZpbGw9IiM2NjYiID4uZ2VuZXJhbGl6YXRpb24uZ2VuZXJhbDwvdGV4dD4gPC9nPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTAsIDI1MCkiPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBMZXZlbCAxIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBPYmplY3QucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPk9iamVjdC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gTGV2ZWwgMiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gSW5zdGFuY2UucHJvdG90eXBlIC0+IE9iamVjdC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSIzNzUiIHkxPSIxMDAiIHgyPSIzNzUiIHkyPSI1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gSW5zdGFuY2UucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDEwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+SW5zdGFuY2UucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIExldmVsIDMgLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIEVsZW1lbnQucHJvdG90eXBlIC0+IEluc3RhbmNlLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjIwMCIgeDI9IjM3NSIgeTI9IjE1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gRWxlbWVudC5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgMjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5FbGVtZW50LnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBMZXZlbCA0IC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBOYW1lZEVsZW1lbnQucHJvdG90eXBlIC0+IEVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iMzc1IiB5MT0iMzAwIiB4Mj0iMzc1IiB5Mj0iMjUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBOYW1lZEVsZW1lbnQucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDMwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+TmFtZWRFbGVtZW50LnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIEdlbmVyYWxpemF0aW9uLnByb3RvdHlwZSAtPiBFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1IiB5MT0iMzAwIiB4Mj0iMzc1IiB5Mj0iMjUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBHZW5lcmFsaXphdGlvbi5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MCwgMzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5HZW5lcmFsaXphdGlvbi5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gTGV2ZWwgNSAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtPiBOYW1lZEVsZW1lbnQucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iMzc1IiB5MT0iNDAwIiB4Mj0iMzc1IiB5Mj0iMzUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBQYWNrYWdlYWJsZUVsZW1lbnQucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNTAsIDQwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+UGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIFR5cGVkRWxlbWVudC5wcm90b3R5cGUgLT4gTmFtZWRFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijk3NSIgeTE9IjQwMCIgeDI9IjM3NSIgeTI9IjM1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gVHlwZWRFbGVtZW50LnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODUwLCA0MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPlR5cGVkRWxlbWVudC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gTGV2ZWwgNiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gVHlwZS5wcm90b3R5cGUgLT4gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjUwMCIgeDI9IjM3NSIgeTI9IjQ1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gVHlwZS5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgNTAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5UeXBlLnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIFR5SW5zdGFuY2VTcGVjaWZpY2F0aW9ucGUucHJvdG90eXBlIC0+IFBhY2thZ2VhYmxlRWxlbWVudC5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI3NSIgeTE9IjUwMCIgeDI9IjM3NSIgeTI9IjQ1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gSW5zdGFuY2VTcGVjaWZpY2F0aW9uLnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUwLCA1MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPkluc3RhbmNlU3BlY2lmaWNhdGlvbi5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBTdHJ1Y3R1cmFsRmVhdHVyZS5wcm90b3R5cGUgLT4gVHlwZWRFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijk3NSIgeTE9IjUwMCIgeDI9Ijk3NSIgeTI9IjQ1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gU3RydWN0dXJhbEZlYXR1cmUucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg4NTAsIDUwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+U3RydWN0dXJhbEZlYXR1cmUucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gUGFja2FnZS5wcm90b3R5cGUgLT4gUGFja2FnZWFibGVFbGVtZW50LnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjY3NSIgeTE9IjUwMCIgeDI9IjM3NSIgeTI9IjQ1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gUGFja2FnZS5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU1MCwgNTAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5QYWNrYWdlLnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBMZXZlbCA3IC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBDbGFzc2lmaWVyLnByb3RvdHlwZSAtPiBUeXBlLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjYwMCIgeDI9IjM3NSIgeTI9IjU1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gQ2xhc3NpZmllci5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgNjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5DbGFzc2lmaWVyLnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIEVudW1lcmF0aW9uTGl0ZXJhbC5wcm90b3R5cGUgLT4gSW5zdGFuY2VTcGVjaWZpY2F0aW9uLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9Ijc1IiB5MT0iNjAwIiB4Mj0iNzUiIHkyPSI1NTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIEVudW1lcmF0aW9uTGl0ZXJhbC5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01MCwgNjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5FbnVtZXJhdGlvbkxpdGVyYWwucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gTW9kZWwucHJvdG90eXBlIC0+IFBhY2thZ2UucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNjc1IiB5MT0iNjAwIiB4Mj0iNjc1IiB5Mj0iNTUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBNb2RlbC5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU1MCwgNjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5Nb2RlbC5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBQcm9wZXJ0eS5wcm90b3R5cGUgLT4gU3RydWN0dXJhbEZlYXR1cmUucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iOTc1IiB5MT0iNjAwIiB4Mj0iOTc1IiB5Mj0iNTUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBQcm9wZXJ0eS5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDg1MCwgNjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5Qcm9wZXJ0eS5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gTGV2ZWwgOCAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gQ2xhc3MucHJvdG90eXBlIC0+IENsYXNzaWZpZXIucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iMzc1IiB5MT0iNzAwIiB4Mj0iMzc1IiB5Mj0iNjUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBDbGFzcy5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgNzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+Q2xhc3MucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gRGF0YVR5cGUucHJvdG90eXBlIC0+IENsYXNzaWZpZXIucHJvdG90eXBlIC0tPiA8bGluZSB4MT0iNjc1IiB5MT0iNzAwIiB4Mj0iMzc1IiB5Mj0iNjUwIiBjbGFzcz0icHJvdG8tbGluZSIgbWFya2VyLWVuZD0idXJsKCNwcm90by1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBEYXRhVHlwZS5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU1MCwgNzAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5EYXRhVHlwZS5wcm90b3R5cGU8L3RleHQ+IDwvZz4gPCEtLSBBc3NvY2lhdGlvbi5wcm90b3R5cGUgLT4gQ2xhc3NpZmllci5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI3NSIgeTE9IjcwMCIgeDI9IjM3NSIgeTI9IjY1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gQXNzb2NpYXRpb24ucHJvdG90eXBlIC0tPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNTAsIDcwMCkiPiA8cmVjdCB3aWR0aD0iMjUwIiBoZWlnaHQ9IjUwIiBjbGFzcz0ib2JqZWN0IiBmaWxsPSJ1cmwoI29iamVjdC1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+QXNzb2NpYXRpb24ucHJvdG90eXBlPC90ZXh0PiA8L2c+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIExldmVsIDkgLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIFByaW1pdGl2ZVR5cGUucHJvdG90eXBlIC0+IERhdGFUeXBlLnByb3RvdHlwZSAtLT4gPGxpbmUgeDE9IjY3NSIgeTE9IjgwMCIgeDI9IjY3NSIgeTI9Ijc1MCIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDwhLS0gUHJpbWl0aXZlVHlwZS5wcm90b3R5cGUgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU1MCwgODAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJvYmplY3QiIGZpbGw9InVybCgjb2JqZWN0LWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5QcmltaXRpdmVUeXBlLnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8IS0tIEVudW1lcmF0aW9uLnByb3RvdHlwZSAtPiBEYXRhVHlwZS5wcm90b3R5cGUgLS0+IDxsaW5lIHgxPSI5NzUiIHkxPSI4MDAiIHgyPSI2NzUiIHkyPSI3NTAiIGNsYXNzPSJwcm90by1saW5lIiBtYXJrZXItZW5kPSJ1cmwoI3Byb3RvLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIEVudW1lcmF0aW9uLnByb3RvdHlwZSAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODUwLCA4MDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9Im9iamVjdCIgZmlsbD0idXJsKCNvYmplY3QtYmFja2dyb3VuZCkiID48L3JlY3Q+IDx0ZXh0IHg9IjE1IiB5PSIzMCIgPkVudW1lcmF0aW9uLnByb3RvdHlwZTwvdGV4dD4gPC9nPiA8L2c+IDwvc3ZnPg== "Metamodel Prototype Hierarchy")

And here is the same look, at the Class Hierarchy:

![Metamodel Class Hierarchy](data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PiA8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPiA8c3ZnIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjEyNTAiIGhlaWdodD0iMTE1MCIgPiA8c3R5bGU+IHN2ZyB7IGZvbnQtZmFtaWx5OiBBcmlhbCwgSGVsdmV0aWNhLCBzYW5zLXNlcmlmOyB9IC5sZWdlbmQgcmVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyBmaWxsOiBub25lOyB9IC5wcm90by1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IGZpbGw6IG5vbmU7IH0gLmNvbnN0cnVjdG9yLWxpbmUgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMjsgc3Ryb2tlLWRhc2hhcnJheTogMiwgMjsgZmlsbDogbm9uZTsgfSAuZ2VuZXJhbC1saW5lIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDI7IHN0cm9rZS1kYXNoYXJyYXk6IDUsIDU7IGZpbGw6IG5vbmU7IH0gLmZ1bmN0aW9uIHsgc3Ryb2tlOiAjNjY2OyBzdHJva2Utd2lkdGg6IDM7IH0gLm9iamVjdCB7IHN0cm9rZTogIzY2Njsgc3Ryb2tlLXdpZHRoOiAzOyB9IC5ibGFjay1ib3JkZXIgeyBzdHJva2U6ICM2NjY7IHN0cm9rZS13aWR0aDogMzsgfSA8L3N0eWxlPiA8ZGVmcz4gPG1hcmtlciBpZD0icHJvdG8tYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjciIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWdvbiBwb2ludHM9IjEgMSwgOSA0LCAxIDciIGZpbGw9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtc3RhcnQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSIxIiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlsaW5lIHBvaW50cz0iOSAxLCAxIDQsIDkgNyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiAvPiA8L21hcmtlcj4gPG1hcmtlciBpZD0iY29uc3RydWN0b3ItYXJyb3doZWFkLWVuZCIgbWFya2VyV2lkdGg9IjEwIiBtYXJrZXJIZWlnaHQ9IjgiIHJlZlg9IjgiIHJlZlk9IjQiIG9yaWVudD0iYXV0byIgPiA8cG9seWxpbmUgcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSJub25lIiBzdHJva2U9IiM2NjYiIC8+IDwvbWFya2VyPiA8bWFya2VyIGlkPSJnZW5lcmFsLWFycm93aGVhZC1lbmQiIG1hcmtlcldpZHRoPSIxMCIgbWFya2VySGVpZ2h0PSI4IiByZWZYPSI3IiByZWZZPSI0IiBvcmllbnQ9ImF1dG8iID4gPHBvbHlnb24gcG9pbnRzPSIxIDEsIDkgNCwgMSA3IiBmaWxsPSIjNjY2IiAvPiA8L21hcmtlcj4gPGxpbmVhckdyYWRpZW50IGlkPSJmdW5jdGlvbi1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoNjIsIDIwMCwgMjU1KTtzdG9wLW9wYWNpdHk6MSIgLz4gPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMCwgMTI3LCAyMzEpO3N0b3Atb3BhY2l0eToxIiAvPiA8L2xpbmVhckdyYWRpZW50PiA8bGluZWFyR3JhZGllbnQgaWQ9Im9iamVjdC1iYWNrZ3JvdW5kIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSIgPiA8c3RvcCBvZmZzZXQ9IjAlIiBzdHlsZT0ic3RvcC1jb2xvcjpyZ2IoMjU1LCAyNDAsIDEwNyk7c3RvcC1vcGFjaXR5OjEiIC8+IDxzdG9wIG9mZnNldD0iMTAwJSIgc3R5bGU9InN0b3AtY29sb3I6cmdiKDIzMSwgMTMxLCAwKTtzdG9wLW9wYWNpdHk6MSIgLz4gPC9saW5lYXJHcmFkaWVudD4gPC9kZWZzPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMCwgMTApIiBjbGFzcz0ibGVnZW5kIiA+IDxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMTI1IiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMjUiIGZpbGw9IiM2NjYiID5MZWdlbmQ8L3RleHQ+IDxsaW5lIHgxPSIxNSIgeTE9IjQ3IiB4Mj0iNzUiIHkyPSI0NyIgY2xhc3M9InByb3RvLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjcHJvdG8tYXJyb3doZWFkLWVuZCkiIC8+IDx0ZXh0IHg9IjEwMCIgeT0iNTAiIGZpbGw9IiM2NjYiID4uX19wcm90b19fPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI3MiIgeDI9Ijc1IiB5Mj0iNzIiIGNsYXNzPSJjb25zdHJ1Y3Rvci1saW5lIiBtYXJrZXItc3RhcnQ9InVybCgjY29uc3RydWN0b3ItYXJyb3doZWFkLXN0YXJ0KSIgbWFya2VyLWVuZD0idXJsKCNjb25zdHJ1Y3Rvci1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSI3NSIgZmlsbD0iIzY2NiIgPi5wcm90b3R5cGUvLmNvbnN0cnVjdG9yPC90ZXh0PiA8bGluZSB4MT0iMTUiIHkxPSI5NyIgeDI9Ijc1IiB5Mj0iOTciIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPHRleHQgeD0iMTAwIiB5PSIxMDAiIGZpbGw9IiM2NjYiID4uZ2VuZXJhbGl6YXRpb24uZ2VuZXJhbDwvdGV4dD4gPC9nPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMTAsIDUwKSI+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIExldmVsIDMgLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqIC0tPiA8IS0tIEVsZW1lbnQgLS0+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI1MCwgMjAwKSI+IDxyZWN0IHdpZHRoPSIyNTAiIGhlaWdodD0iNTAiIGNsYXNzPSJmdW5jdGlvbiIgZmlsbD0idXJsKCNmdW5jdGlvbi1iYWNrZ3JvdW5kKSIgPjwvcmVjdD4gPHRleHQgeD0iMTUiIHk9IjMwIiA+RWxlbWVudDwvdGV4dD4gPC9nPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBMZXZlbCA0IC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBOYW1lZEVsZW1lbnQgLT4gRWxlbWVudCAtLT4gPGxpbmUgeDE9IjM3NSIgeTE9IjMwMCIgeDI9IjM3NSIgeTI9IjI1MCIgY2xhc3M9ImdlbmVyYWwtbGluZSIgbWFya2VyLWVuZD0idXJsKCNnZW5lcmFsLWFycm93aGVhZC1lbmQpIiAvPiA8IS0tIE5hbWVkRWxlbWVudCAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLCAzMDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9ImZ1bmN0aW9uIiBmaWxsPSJ1cmwoI2Z1bmN0aW9uLWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5OYW1lZEVsZW1lbnQ8L3RleHQ+IDwvZz4gPCEtLSBHZW5lcmFsaXphdGlvbiAtPiBFbGVtZW50IC0tPiA8bGluZSB4MT0iNzUiIHkxPSIzMDAiIHgyPSIzNzUiIHkyPSIyNTAiIGNsYXNzPSJnZW5lcmFsLWxpbmUiIG1hcmtlci1lbmQ9InVybCgjZ2VuZXJhbC1hcnJvd2hlYWQtZW5kKSIgLz4gPCEtLSBHZW5lcmFsaXphdGlvbiAtLT4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUwLCAzMDApIj4gPHJlY3Qgd2lkdGg9IjI1MCIgaGVpZ2h0PSI1MCIgY2xhc3M9ImZ1bmN0aW9uIiBmaWxsPSJ1cmwoI2Z1bmN0aW9uLWJhY2tncm91bmQpIiA+PC9yZWN0PiA8dGV4dCB4PSIxNSIgeT0iMzAiID5HZW5lcmFsaXphdGlvbjwvdGV4dD4gPC9nPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogLS0+IDwhLS0gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAtLT4gPCEtLSBMZXZlbCA1IC0tPiA8IS0tICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKio