function createPropertyStructure( rawProperties, classMap, propertyMap ){
	    var properties = [];
	    // Set default values
	    rawProperties.forEach(function ( property ){
	      property.visible(true);
	    });

	    // Connect properties
	    rawProperties.forEach(function ( property ){
	      var domain,
	        range,
	        domainObject,
	        rangeObject,
	        inverse;

	      /* Skip properties that have no information about their domain and range, like
	       inverse properties with optional inverse and optional domain and range attributes */
	      if ( (property.domain() && property.range()) || property.inverse() ) {

	        var inversePropertyId = findId(property.inverse());
	        // Look if an inverse property exists
	        if ( inversePropertyId ) {
	          inverse = propertyMap[inversePropertyId];
	          if ( !inverse ) {
	            console.warn("No inverse property was found for id: " + inversePropertyId);
	            property.inverse(undefined);
	          }
	        }

	        // Either domain and range are set on this property or at the inverse
	        if ( typeof property.domain() !== "undefined" && typeof property.range() !== "undefined" ) {
	          domain = findId(property.domain());
	          range = findId(property.range());

	          domainObject = classMap[domain];
	          rangeObject = classMap[range];
	        } else if ( inverse ) {
	          // Domain and range need to be switched
	          domain = findId(inverse.range());
	          range = findId(inverse.domain());

	          domainObject = classMap[domain];
	          rangeObject = classMap[range];
	        } else {
	          console.warn("Domain and range not found for property: " + property.id());
	        }

	        // Set the references on this property
	        property.domain(domainObject);
	        property.range(rangeObject);

	        // Also set the attributes of the inverse property
	        if ( inverse ) {
	          property.inverse(inverse);
	          inverse.inverse(property);

	          // Switch domain and range
	          inverse.domain(rangeObject);
	          inverse.range(domainObject);
	        }
	      }
	      // Reference sub- and superproperties
	      referenceSubOrSuperProperties(property.subproperties());
	      referenceSubOrSuperProperties(property.superproperties());
	    });

	    // Merge equivalent properties and process disjoints.
	    rawProperties.forEach(function ( property ){
	      processEquivalentIds(property, propertyMap);
	      processDisjoints(property);

	      attributeParser.parsePropertyAttributes(property);
	    });
	    // Add additional information to the properties
	    rawProperties.forEach(function ( property ){
	      // Properties of merged classes should point to/from the visible equivalent class
	      var propertyWasRerouted = false;

	      if ( property.domain() === undefined ) {
	        console.warn("No Domain was found for id:" + property.id());
	        return;
	      }

	      if ( wasNodeMerged(property.domain()) ) {
	        property.domain(property.domain().equivalentBase());
	        propertyWasRerouted = true;
	      }
	      if ( property.range() === undefined ) {
	        console.warn("No range was found for id:" + property.id());
	        return;
	      }
	      if ( wasNodeMerged(property.range()) ) {
	        property.range(property.range().equivalentBase());
	        propertyWasRerouted = true;
	      }
	      // But there should not be two equal properties between the same domain and range
	      var equalProperty = getOtherEqualProperty(rawProperties, property);

	      if ( propertyWasRerouted && equalProperty ) {
	        property.visible(false);

	        equalProperty.redundantProperties().push(property);
	      }

	      // Hide property if source or target node is hidden
	      if ( !property.domain().visible() || !property.range().visible() ) {
	        property.visible(false);
	      }

	      // Collect all properties that should be displayed
	      if ( property.visible() ) {
	        properties.push(property);
	      }
	    });
	    return properties;
	  }
/**
	   * Connect all properties and also their sub- and superproperties.
	   * We iterate over the rawProperties array because it is way faster than iterating
	   * over an object and its attributes.
	   *
	   * @param rawProperties the properties
	   * @param classMap a map of all classes
	   * @param propertyMap the properties in a map
	   */
Connect all properties and also their sub- and superproperties.
We iterate over the rawProperties array because it is way faster than iterating
over an object and its attributes.

@param rawProperties the properties
@param classMap a map of all classes
@param propertyMap the properties in a map
Connect all properties and also their sub - and superproperties . We iterate over the rawProperties array because it is way faster than iterating over an object and its attributes . @param rawProperties the properties @param classMap a map of all classes @param propertyMap the properties in a map
function createPropertyStructure( rawProperties, classMap, propertyMap ){
	    var properties = [];
	    rawProperties.forEach(function ( property ){
	      property.visible(true);
	    });
	    rawProperties.forEach(function ( property ){
	      var domain,
	        range,
	        domainObject,
	        rangeObject,
	        inverse;
	      if ( (property.domain() && property.range()) || property.inverse() ) {
	        var inversePropertyId = findId(property.inverse());
	        if ( inversePropertyId ) {
	          inverse = propertyMap[inversePropertyId];
	          if ( !inverse ) {
	            console.warn("No inverse property was found for id: " + inversePropertyId);
	            property.inverse(undefined);
	          }
	        }
	        if ( typeof property.domain() !== "undefined" && typeof property.range() !== "undefined" ) {
	          domain = findId(property.domain());
	          range = findId(property.range());
	          domainObject = classMap[domain];
	          rangeObject = classMap[range];
	        } else if ( inverse ) {
	          domain = findId(inverse.range());
	          range = findId(inverse.domain());
	          domainObject = classMap[domain];
	          rangeObject = classMap[range];
	        } else {
	          console.warn("Domain and range not found for property: " + property.id());
	        }
	        property.domain(domainObject);
	        property.range(rangeObject);
	        if ( inverse ) {
	          property.inverse(inverse);
	          inverse.inverse(property);
	          inverse.domain(rangeObject);
	          inverse.range(domainObject);
	        }
	      }
	      referenceSubOrSuperProperties(property.subproperties());
	      referenceSubOrSuperProperties(property.superproperties());
	    });
	    rawProperties.forEach(function ( property ){
	      processEquivalentIds(property, propertyMap);
	      processDisjoints(property);
	      attributeParser.parsePropertyAttributes(property);
	    });
	    rawProperties.forEach(function ( property ){
	      var propertyWasRerouted = false;
	      if ( property.domain() === undefined ) {
	        console.warn("No Domain was found for id:" + property.id());
	        return;
	      }
	      if ( wasNodeMerged(property.domain()) ) {
	        property.domain(property.domain().equivalentBase());
	        propertyWasRerouted = true;
	      }
	      if ( property.range() === undefined ) {
	        console.warn("No range was found for id:" + property.id());
	        return;
	      }
	      if ( wasNodeMerged(property.range()) ) {
	        property.range(property.range().equivalentBase());
	        propertyWasRerouted = true;
	      }
	      var equalProperty = getOtherEqualProperty(rawProperties, property);
	      if ( propertyWasRerouted && equalProperty ) {
	        property.visible(false);
	        equalProperty.redundantProperties().push(property);
	      }
	      if ( !property.domain().visible() || !property.range().visible() ) {
	        property.visible(false);
	      }
	      if ( property.visible() ) {
	        properties.push(property);
	      }
	    });
	    return properties;
	  }
function createPropertyStructure ( rawProperties , classMap , propertyMap ) { var properties = [ ] ; rawProperties . forEach ( function ( property ) { property . visible ( true ) ; } ) ; rawProperties . forEach ( function ( property ) { var domain , range , domainObject , rangeObject , inverse ; if ( ( property . domain ( ) && property . range ( ) ) || property . inverse ( ) ) { var inversePropertyId = findId ( property . inverse ( ) ) ; if ( inversePropertyId ) { inverse = propertyMap [ inversePropertyId ] ; if ( ! inverse ) { console . warn ( "No inverse property was found for id: " + inversePropertyId ) ; property . inverse ( undefined ) ; } } if ( typeof property . domain ( ) !== "undefined" && typeof property . range ( ) !== "undefined" ) { domain = findId ( property . domain ( ) ) ; range = findId ( property . range ( ) ) ; domainObject = classMap [ domain ] ; rangeObject = classMap [ range ] ; } else if ( inverse ) { domain = findId ( inverse . range ( ) ) ; range = findId ( inverse . domain ( ) ) ; domainObject = classMap [ domain ] ; rangeObject = classMap [ range ] ; } else { console . warn ( "Domain and range not found for property: " + property . id ( ) ) ; } property . domain ( domainObject ) ; property . range ( rangeObject ) ; if ( inverse ) { property . inverse ( inverse ) ; inverse . inverse ( property ) ; inverse . domain ( rangeObject ) ; inverse . range ( domainObject ) ; } } referenceSubOrSuperProperties ( property . subproperties ( ) ) ; referenceSubOrSuperProperties ( property . superproperties ( ) ) ; } ) ; rawProperties . forEach ( function ( property ) { processEquivalentIds ( property , propertyMap ) ; processDisjoints ( property ) ; attributeParser . parsePropertyAttributes ( property ) ; } ) ; rawProperties . forEach ( function ( property ) { var propertyWasRerouted = false ; if ( property . domain ( ) === undefined ) { console . warn ( "No Domain was found for id:" + property . id ( ) ) ; return ; } if ( wasNodeMerged ( property . domain ( ) ) ) { property . domain ( property . domain ( ) . equivalentBase ( ) ) ; propertyWasRerouted = true ; } if ( property . range ( ) === undefined ) { console . warn ( "No range was found for id:" + property . id ( ) ) ; return ; } if ( wasNodeMerged ( property . range ( ) ) ) { property . range ( property . range ( ) . equivalentBase ( ) ) ; propertyWasRerouted = true ; } var equalProperty = getOtherEqualProperty ( rawProperties , property ) ; if ( propertyWasRerouted && equalProperty ) { property . visible ( false ) ; equalProperty . redundantProperties ( ) . push ( property ) ; } if ( ! property . domain ( ) . visible ( ) || ! property . range ( ) . visible ( ) ) { property . visible ( false ) ; } if ( property . visible ( ) ) { properties . push ( property ) ; } } ) ; return properties ; }
Connect all properties and also their sub- and superproperties.
Connect all properties and also their sub - and superproperties .
// Set default values // Connect properties /* Skip properties that have no information about their domain and range, like
	       inverse properties with optional inverse and optional domain and range attributes */ // Look if an inverse property exists // Either domain and range are set on this property or at the inverse // Domain and range need to be switched // Set the references on this property // Also set the attributes of the inverse property // Switch domain and range // Reference sub- and superproperties // Merge equivalent properties and process disjoints. // Add additional information to the properties // Properties of merged classes should point to/from the visible equivalent class // But there should not be two equal properties between the same domain and range // Hide property if source or target node is hidden // Collect all properties that should be displayed