https://fedorahosted.org/freeipa/ticket/1531

(3.0 Core Effort Iteration 01 September Y11 Release)

Implemented solution:
 * all entities are created on application start
* dependant objects (facets and dialogs) are created at once on their first use in entity.

Note(patch naming): patch 022 was second part of 021, but the file name was wrong(021-1)
--
Petr Vobornik
From 4785e6bbc9d4254025bb3e06e865f2eccac9f36f Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Mon, 10 Oct 2011 13:34:15 +0200
Subject: [PATCH] Circular entity dependency

https://fedorahosted.org/freeipa/ticket/1531

Each entity is created together with its dependent objects (e.g. facets and dialog boxes). This causes a circular dependency problem because some of the objects need to obtain a reference to another entity that has not been created.

Currently this is handled by storing only the other entity name and resolve it when needed (e.g. during rendering stage). In IPA.search_facet this delays the creation of the table widget, making it more difficult to customize.

One solution is to do the object creation in 2 steps:

 * create all entity objects only
 * create the dependent objects in each entity

Implemented solution:
 * all entities are created on application start
 * dependant objects (facets and dialogs) are created at once on their first use in entity.
---
 install/ui/details.js    |   23 ++++
 install/ui/entity.js     |  308 +++++++++++++++++++++++++++++++--------------
 install/ui/navigation.js |    6 +-
 install/ui/search.js     |    4 +-
 4 files changed, 240 insertions(+), 101 deletions(-)

diff --git a/install/ui/details.js b/install/ui/details.js
index e25c45875bcf4950e0c3085fd3930aea764d35bb..1e4a9eb5f1148cb109a89d0affd6aee3c4c6eefd 100644
--- a/install/ui/details.js
+++ b/install/ui/details.js
@@ -295,6 +295,27 @@ IPA.details_facet = function(spec) {
 
     that.sections = $.ordered_map();
 
+    that.add_sections = function(sections) {
+
+        if(sections) {
+            for(var i=0; i < sections.length; i++) {
+
+                    var section_spec = sections[i];
+                    section_spec.entity = that.entity;
+
+                    if (!section_spec.label) {
+                        var obj_messages = IPA.messages.objects[that.entity.name];
+                        section_spec.label = obj_messages[section_spec.name];
+                    }
+
+                    section_spec.factory = section_spec.factory || IPA.details_table_section;
+                    var section = section_spec.factory(section_spec);
+
+                    that.add_section(section);
+            }
+        }
+    };
+
     that.dirty = false;
 
     that.add_section = function(section) {
@@ -717,6 +738,8 @@ IPA.details_facet = function(spec) {
         command.execute();
     };
 
+    that.add_sections(spec.sections);
+
     that.details_facet_create_content = that.create_content;
     that.details_facet_load = that.load;
 
diff --git a/install/ui/entity.js b/install/ui/entity.js
index 3742360115d9dda51f35132b648d785a600d38f3..7545c8a2ba66aecde8da07bf1f5248d2aba08b55 100644
--- a/install/ui/entity.js
+++ b/install/ui/entity.js
@@ -128,7 +128,7 @@ IPA.facet = function (spec) {
     that.redirect = function() {
         var entity = that.entity;
         while (entity.containing_entity) {
-            entity = entity.containing_entity;
+            entity = entity.get_containing_entity();
         }
 
         IPA.nav.show_page(
@@ -192,13 +192,13 @@ IPA.facet_header = function(spec) {
 
         if (!that.facet.disable_breadcrumb) {
             var breadcrumb = [];
-            var entity = that.facet.entity.containing_entity;
+            var entity = that.facet.entity.get_containing_entity();
 
             while (entity) {
                 breadcrumb.unshift($('<a/>', {
                     'class': 'breadcrumb-element',
                     text: IPA.nav.get_state(entity.name+'-pkey'),
-                    title: entity.name,
+                    title: entity.title,
                     click: function(entity) {
                         return function() {
                             IPA.nav.show_page(entity.name, 'default');
@@ -207,7 +207,7 @@ IPA.facet_header = function(spec) {
                     }(entity)
                 }));
 
-                entity = entity.containing_entity;
+                entity = entity.get_containing_entity();
             }
 
             that.path.empty();
@@ -293,7 +293,9 @@ IPA.facet_header = function(spec) {
             }).appendTo(that.breadcrumb);
 
             var entity = that.facet.entity;
-            while (entity.containing_entity) entity = entity.containing_entity;
+            while (entity.containing_entity) {
+                entity = entity.get_containing_entity();
+            }
 
             $('<a/>', {
                 text: entity.metadata.label,
@@ -453,9 +455,13 @@ IPA.entity = function (spec) {
     that.title = spec.title || that.label;
 
     that.dialogs = $.ordered_map();
+    that.dialog_specs = spec.dialogs || [];
+    that.dialogs_created = false;
 
     that.facets = $.ordered_map();
     that.facet_groups = $.ordered_map();
+    that.facet_specs = spec.facets || [];
+    that.facets_created = false;
 
     // current facet
     that.facet = null;
@@ -463,7 +469,20 @@ IPA.entity = function (spec) {
     that.redirect_facet = spec.redirect_facet;
     that.containing_entity = null;
 
+    that.get_containing_entity = function() {
+        return that.containing_entity ?
+        IPA.get_entity(that.containing_entity) : null;
+    };
+
     that.get_dialog = function(name) {
+
+        //build all dialogs on the first time
+        if(!that.dialogs_created) {
+            var builder = IPA.dialog_builder(that);
+            builder.build_dialogs();
+            that.dialogs_created = true;
+        }
+
         return that.dialogs.get(name);
     };
 
@@ -490,6 +509,14 @@ IPA.entity = function (spec) {
     };
 
     that.get_facet = function(name) {
+
+        //build all facets on the first time
+        if(!that.facets_created) {
+            var builder = IPA.facet_builder(that);
+            builder.build_facets();
+            that.facets_created = true;
+        }
+
         if (name === undefined) {
             // return the current facet
             if (that.facet) return that.facet;
@@ -570,14 +597,14 @@ IPA.entity = function (spec) {
     that.get_primary_key_prefix = function() {
         var pkey = [];
         var current_entity = that;
-        current_entity = current_entity.containing_entity;
+        current_entity = current_entity.get_containing_entity();
         while(current_entity !== null){
 
             var key = IPA.nav.get_state(current_entity.name+'-pkey');
             if (key){
                 pkey.unshift(key);
             }
-            current_entity = current_entity.containing_entity;
+            current_entity = current_entity.get_containing_entity();
         }
         return pkey;
     };
@@ -734,20 +761,19 @@ IPA.entity_builder = function(){
     };
 
     that.facet = function(spec) {
+
         spec.entity  = entity;
-        facet = spec.factory(spec);
-        entity.add_facet(facet);
+        entity.facet_specs.push(spec);
+
         return that;
     };
 
     that.search_facet = function(spec) {
-        spec.entity = entity;
-        spec.title = spec.title || entity.metadata.label;
-        spec.label = spec.label || IPA.messages.facets.search;
 
-        var factory = spec.factory || IPA.search_facet;
-        facet = factory(spec);
-        entity.add_facet(facet);
+        spec.type = spec.type || 'search';
+
+        that.facet(spec);
+
         add_redirect_info();
 
         return that;
@@ -755,81 +781,27 @@ IPA.entity_builder = function(){
 
     that.nested_search_facet = function(spec) {
 
-        spec.entity = entity;
-        spec.title = spec.title || entity.metadata.label_singular;
-        spec.label = spec.label || IPA.messages.facets.search;
+        spec.type = spec.type || 'nested_search';
 
-        var factory = spec.factory || IPA.nested_search_facet;
-        facet = factory(spec);
-        entity.add_facet(facet);
+        that.facet(spec);
 
         return that;
     };
 
     that.details_facet = function(spec) {
 
-        var sections = spec.sections;
-        spec.entity = entity;
-        spec.sections = null;
-        spec.title = spec.title || entity.metadata.label_singular;
-        spec.label = spec.label || IPA.messages.facets.details;
+        spec.type = spec.type || 'details';
 
-        var factory = spec.factory || IPA.details_facet;
-        facet = factory(spec);
-        entity.add_facet(facet);
-
-        if (sections) {
-            for (var i=0; i<sections.length; i++) {
-                that.section(sections[i]);
-            }
-        }
+        that.facet(spec);
 
         return that;
     };
 
     that.association_facet = function(spec) {
 
-        spec.entity = entity;
+        spec.type = spec.type || 'association';
 
-        var index = spec.name.indexOf('_');
-        spec.attribute_member = spec.attribute_member ||
-            spec.name.substring(0, index);
-        spec.other_entity = spec.other_entity ||
-            spec.name.substring(index+1);
-
-        spec.add_title = IPA.messages.association.add[spec.attribute_member];
-        spec.remove_title = IPA.messages.association.remove[spec.attribute_member];
-
-        spec.facet_group = spec.facet_group ||
-            spec.attribute_member;
-
-        if (spec.facet_group == 'memberindirect' ||
-            spec.facet_group == 'memberofindirect') {
-
-            var length = spec.attribute_member.length;
-            var direct_attribute_member = spec.attribute_member.substring(0, length-8);
-            var direct_facet_name = direct_attribute_member+'_'+spec.other_entity;
-
-            facet = entity.get_facet(direct_facet_name);
-
-            if (facet) { // merge into previously created direct facet
-                facet.indirect_attribute_member = spec.attribute_member;
-                return that;
-
-            } else {
-                spec.read_only = true;
-            }
-        }
-
-        spec.title = spec.label || entity.metadata.label_singular;
-
-        spec.label = spec.label ||
-            (IPA.metadata.objects[spec.other_entity] ?
-             IPA.metadata.objects[spec.other_entity].label : spec.other_entity);
-
-        var factory = spec.factory || IPA.association_facet;
-        facet = factory(spec);
-        entity.add_facet(facet);
+        that.facet(spec);
 
         return that;
     };
@@ -863,7 +835,7 @@ IPA.entity_builder = function(){
                 var other_entity = other_entities[j];
                 var association_name = attribute_member+'_'+other_entity;
 
-                var facet = entity.get_facet(association_name);
+                var facet = get_spec_by_name(entity.facet_specs, association_name);
                 if (facet) continue;
 
                 var tmp_spec = $.extend({}, spec);
@@ -876,21 +848,17 @@ IPA.entity_builder = function(){
         return that;
     };
 
-    that.section = function(spec) {
-        spec.entity = entity;
+    function get_spec_by_name(specs, name) {
+        if(!specs || !specs.length) return null;
 
-        if (!spec.label) {
-            var obj_messages = IPA.messages.objects[entity.name];
-            spec.label = obj_messages[spec.name];
+        for(var i=0; i<specs.length; i++) {
+            if(specs[i].name === name) {
+                return specs[i];
+            }
         }
 
-        if (spec.factory) {
-            section = spec.factory(spec);
-        } else {
-            section = IPA.details_table_section(spec);
-        }
-        facet.add_section(section);
-    };
+        return null;
+    }
 
     function add_redirect_info(facet_name){
         if (!entity.redirect_facet){
@@ -900,30 +868,31 @@ IPA.entity_builder = function(){
 
     that.containing_entity = function(entity_name) {
         add_redirect_info();
-        entity.containing_entity = IPA.get_entity(entity_name);
+        entity.containing_entity = entity_name;
         return that;
     };
 
     that.dialog = function(spec) {
-        var dialog;
+
         if (spec instanceof Object) {
-            var factory = spec.factory || IPA.dialog;
+            spec.factory = spec.factory || IPA.dialog;
             spec.entity = entity;
-            dialog = factory(spec);
+
         } else {
-            dialog = IPA.dialog({
+            spec = {
+                factory: IPA.dialog,
                 name: spec,
                 entity: entity
-            });
+            };
         }
-        entity.dialog(dialog);
+
+        entity.dialog_specs.push(spec);
         return that;
     };
 
     that.adder_dialog = function(spec) {
         spec.factory = spec.factory || IPA.add_dialog;
         spec.name = spec.name || 'add';
-        spec.entity = entity;
 
         if (!spec.title) {
             var title = IPA.messages.dialogs.add_title;
@@ -944,8 +913,155 @@ IPA.entity_builder = function(){
     that.build = function(){
         var item = entity;
         entity = null;
+
         return item;
     };
 
     return that;
 };
+
+IPA.facet_builder = function(entity) {
+
+    var that = {};
+
+    that.build_facets = function() {
+
+        if(entity.facet_specs && entity.facet_specs.length) {
+            var facets = entity.facet_specs;
+            for(var i=0; i<facets.length; i++) {
+                var facet_spec = facets[i];
+                that.build_facet(facet_spec);
+            }
+        }
+    };
+
+    that.build_facet = function(spec) {
+
+        var type = spec.type || 'details';
+        //do common logic
+        spec.entity = entity;
+
+
+        //prepare spec based on type
+        var prepare_method_name = 'prepare_'+type+'_spec';
+        if(that[prepare_method_name] &&
+                typeof that[prepare_method_name] === 'function') {
+            that[prepare_method_name](spec);
+        }
+
+        //add facet
+        var facet = spec.factory(spec);
+        entity.add_facet(facet);
+    };
+
+    function add_redirect_info(facet_name) {
+
+        facet_name = facet_name || 'search';
+        if (!entity.redirect_facet){
+            entity.redirect_facet = facet_name;
+        }
+    }
+
+    that.prepare_search_spec = function(spec) {
+
+        spec.title = spec.title || entity.metadata.label;
+        spec.label = spec.label || IPA.messages.facets.search;
+        spec.factory = spec.factory || IPA.search_facet;
+
+        add_redirect_info();
+        return spec;
+    };
+
+    that.prepare_nested_search_spec = function(spec) {
+
+        spec.title = spec.title || entity.metadata.label_singular;
+        spec.label = spec.label || IPA.messages.facets.search;
+        spec.factory = spec.factory || IPA.nested_search_facet;
+
+        return spec;
+    };
+
+    that.prepare_details_spec = function(spec) {
+        spec.title = spec.title || entity.metadata.label_singular;
+        spec.label = spec.label || IPA.messages.facets.details;
+        spec.factory = spec.factory || IPA.details_facet;
+
+        return spec;
+    };
+
+    that.prepare_association_spec = function(spec) {
+
+        spec.entity = entity;
+
+        var index = spec.name.indexOf('_');
+        spec.attribute_member = spec.attribute_member ||
+        spec.name.substring(0, index);
+        spec.other_entity = spec.other_entity ||
+        spec.name.substring(index+1);
+
+        spec.add_title = IPA.messages.association.add[spec.attribute_member];
+        spec.remove_title = IPA.messages.association.remove[spec.attribute_member];
+
+        spec.facet_group = spec.facet_group || spec.attribute_member;
+
+        spec.factory = spec.factory || IPA.association_facet;
+
+        spec.title = spec.label || entity.metadata.label_singular;
+
+        spec.label = spec.label ||
+            (IPA.metadata.objects[spec.other_entity] ?
+            IPA.metadata.objects[spec.other_entity].label : spec.other_entity);
+
+        if(that.has_indirect_attribute_member(spec)) {
+
+            spec.indirect_attribute_member = spec.attribute_member + 'indirect';
+        }
+
+        if (spec.facet_group === 'memberindirect' ||
+            spec.facet_group === 'memberofindirect') {
+
+            spec.read_only = true;
+        }
+
+        return spec;
+    };
+
+    that.has_indirect_attribute_member = function(spec) {
+
+        var indirect_members = entity.metadata.attribute_members[spec.attribute_member + 'indirect'];
+        if(indirect_members) {
+            if(indirect_members.indexOf(spec.other_entity) > -1) {
+                return true;
+            }
+        }
+        return false;
+    };
+
+    return that;
+};
+
+IPA.dialog_builder = function(entity) {
+
+    var that = {};
+
+    that.build_dialogs = function() {
+
+        if(entity.dialog_specs && entity.dialog_specs.length) {
+            var dialogs = entity.dialog_specs;
+            for(var i=0; i<dialogs.length; i++) {
+                that.build_dialog(dialogs[i]);
+            }
+        }
+    };
+
+    that.build_dialog = function(spec) {
+        //do common logic
+        spec.entity = entity;
+
+        //add dialog
+        var dialog = spec.factory(spec);
+        entity.dialog(dialog);
+    };
+
+    return that;
+};
\ No newline at end of file
diff --git a/install/ui/navigation.js b/install/ui/navigation.js
index 76117342511fc9f33e7c81f58d5c6e2fc132208b..84df7f4daf2fb342f54ff2427cafe1b422789639 100644
--- a/install/ui/navigation.js
+++ b/install/ui/navigation.js
@@ -174,7 +174,7 @@ IPA.navigation = function(spec) {
         // update new facet state with new state
         $.extend(facet.state, param_state);
 
-        var entity = tab.entity.containing_entity;
+        var entity = tab.entity.get_containing_entity();
         while (entity) {
             var facet2 = entity.get_facet();
 
@@ -186,7 +186,7 @@ IPA.navigation = function(spec) {
                 if (key_value) facet.state[key_name] = key_value;
             }
 
-            entity = entity.containing_entity;
+            entity = entity.get_containing_entity();
         }
 
         // push entity path and facet state
@@ -233,7 +233,7 @@ IPA.navigation = function(spec) {
                 var current_entity = entity;
                 while (current_entity){
                     state[current_entity.name + '-pkey'] = pkeys.pop();
-                    current_entity = current_entity.containing_entity;
+                    current_entity = current_entity.get_containing_entity();
                 }
             }else{
                 state[entity.name + '-pkey'] = pkeys;
diff --git a/install/ui/search.js b/install/ui/search.js
index c469debc8f76deac0ba72f60c55f3790b8cc6ea2..fe84c2ed97c4cb31fd7497b1247d38b228987dac 100644
--- a/install/ui/search.js
+++ b/install/ui/search.js
@@ -268,11 +268,11 @@ IPA.search_facet = function(spec) {
         var filter = [];
         var current_entity = entity;
         filter.unshift(IPA.nav.get_state(current_entity.name+'-filter'));
-        current_entity = current_entity.containing_entity;
+        current_entity = current_entity.get_containing_entity();
         while(current_entity !== null){
             filter.unshift(
                 IPA.nav.get_state(current_entity.name+'-pkey'));
-            current_entity = current_entity.containing_entity;
+            current_entity = current_entity.get_containing_entity();
         }
 
         var command = IPA.command({
-- 
1.7.6

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to