src/midgard_style.c

00001 /* 
00002  * Copyright (C) 2005 Piotr Pokora <piotr.pokora@infoglob.pl>
00003  *
00004  * This program is free software; you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License as published
00006  * by the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  * 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  * 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 #include <stdlib.h>
00020 #include <glib.h>
00021 #include "midgard/midgard_datatypes.h"
00022 #include "midgard/midgard_style.h"
00023 #include "midgard/query_builder.h"
00024 
00025 typedef struct{
00026         gchar *name;
00027         GHashTable *table;
00028 }_midgard_style;
00029 
00030 /* Creates a new MgdStyle */
00031 MgdStyle *midgard_style_new(midgard *mgd)
00032 {
00033         MgdStyle *style = g_new(MgdStyle, 1);
00034         style->stack = NULL;
00035         style->styles = g_hash_table_new(g_str_hash, g_str_equal);
00036         style->page_elements = midgard_hash_strings_new();
00037         style->style_elements = midgard_hash_strings_new();
00038         
00039         return style;
00040 }
00041 
00042 static void _get_parent_page_elements(MgdObject *object, GHashTable *table)
00043 {
00044         MgdObject *parent = midgard_object_get_parent(object);
00045 
00046         if(parent == NULL)
00047                 return;
00048         
00049         guint n_objects, i;
00050         GParamSpec *prop;
00051         gchar *name, *value;
00052         MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(parent);
00053         gchar *primary = midgard_object_class_get_primary_property(klass);
00054         
00055         MidgardQueryBuilder *builder = 
00056                 midgard_query_builder_new(parent->mgd, "midgard_pageelement");
00057 
00058         if(!builder) {
00059                 MIDGARD_ERRNO_SET(parent->mgd, MGD_ERR_INTERNAL);
00060                 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
00061                                 "Invalid query builder configuration (%s)",
00062                                 G_OBJECT_TYPE_NAME(G_OBJECT(parent)));
00063                 return;
00064         }
00065 
00066         /* Find object's primary property */
00067         prop = g_object_class_find_property(
00068                         G_OBJECT_GET_CLASS(G_OBJECT(parent)), primary);
00069         
00070         GValue pval = {0,};
00071         /* Initialize primary property value */
00072         g_value_init(&pval,prop->value_type);
00073         g_object_get_property(G_OBJECT(object), primary, &pval);
00074         /* I think we can hardcode parent property */
00075         midgard_query_builder_add_constraint(builder, "page", "=", &pval);
00076         g_value_unset(&pval);
00077         /* Get only those elements which has inheritance set */
00078         g_value_init(&pval,G_TYPE_STRING);
00079         g_value_set_string(&pval, "inherit");
00080         midgard_query_builder_add_constraint(builder, "info", "=", &pval);
00081         g_value_unset(&pval);
00082         
00083         GObject **childs = 
00084                 midgard_query_builder_execute(builder, n_objects);
00085 
00086         for(i = 0; i < n_objects; i++){
00087                 
00088                 g_object_get(G_OBJECT(childs[i]), 
00089                                         "name", &name, 
00090                                         "value", &value,
00091                                         NULL);
00092                 g_hash_table_insert(table,
00093                                 g_strdup(name), g_strdup(value));
00094                 g_object_unref(childs[i]);              
00095         }
00096         midgard_query_builder_free(builder);
00097 
00098         /* Walk to root page */
00099         _get_parent_page_elements(parent, table);
00100         
00101         g_object_unref(parent); 
00102 }
00103 
00104 /* Load page and its elements */
00105 gboolean midgard_style_load_page(MgdStyle *style, MgdObject *object)
00106 {
00107         g_assert(object != NULL);
00108         gchar *title, *content, *name, *value;
00109         MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(object);
00110         gchar *primary = midgard_object_class_get_primary_property(klass);
00111         
00112         /* Get title and content of the page */
00113         g_object_get(G_OBJECT(object), "title", &title, NULL);
00114         g_object_get(G_OBJECT(object), "content", &content, NULL);
00115 
00116         g_hash_table_insert(style->page_elements, "title", g_strdup(title));
00117         g_hash_table_insert(style->page_elements, "content", g_strdup(content));
00118         
00119         /* Get all page elements */
00120         MgdObject **childs = midgard_object_list_childs(object, "midgard_pageelement", &n_objects);
00121         
00122         if(childs != NULL) {
00123                 for(i = 0; i < n_objects; i++){
00124                         
00125                         g_object_get(G_OBJECT(childs[i]), 
00126                                         "name", &name,
00127                                         "value", &value,
00128                                         NULL);
00129                         g_hash_table_insert(style->page_elements,
00130                                         g_strdup(name), g_strdup(value));
00131                         g_object_unref(childs[i]);
00132                 }
00133         }
00134 
00135         /* Walk to root page and collect all page elements, 
00136          * replacing existing elements  with parent's page ones if inherited */
00137         _get_parent_page_elements(object, style->page_elements);
00138 }
00139 
00140 
00141 GHashTable *_style_get_elements_from_dir(midgard *mgd, const gchar *path)        
00142 {
00143         gchar  *content, **ffname, *fpfname = NULL;
00144         const gchar *fname = NULL;
00145         GDir *dir;
00146         GHashTable *elements;
00147         
00148         /* We need full path for multiple midcoms installed and running 
00149          * with the same midgard core version */
00150         /* apath = g_strconcat(MIDGARD_SHARE_DIR, "/", path, NULL); */
00151         
00152         dir = g_dir_open(path, 0, NULL);
00153         if (dir != NULL) {
00154                 
00155                 /* Initialize "elements" ( files ) hash table */
00156                 elements = midgard_hash_strings_new();
00157                 
00158                 /* Read files form directory */
00159                 while ((fname = g_dir_read_name(dir)) != NULL) {
00160                         
00161                         fpfname = g_strconcat( path, "/", fname, NULL);
00162                         /* Get filename without extension. */ 
00163                         ffname = g_strsplit(fname, ".", -1);
00164                    
00165                         /* Get file content and set as value in hash table ,
00166                          * * filename without extension is a key */
00167                         if (g_file_get_contents(fpfname,  &content, NULL, NULL) == TRUE) {
00168                                 
00169                                 g_hash_table_insert(elements, g_strdup(ffname[0]), g_strdup(content));
00170                                 g_free(content);
00171                         }
00172                         g_free(fpfname);
00173                         g_strfreev(ffname);
00174                         
00175                 }
00176                 g_dir_close(dir);
00177                 return elements;
00178         }
00179         return NULL;
00180 }
00181 
00182 
00183 /* This is almost the same function like _get_parent_page_elements.
00184  * I keep them both to avoid plenty of conditions in one function in a future */
00185 static void _get_parent_style_elements(MgdObject *object, GHashTable *table)
00186 {
00187         MgdObject *parent = midgard_object_get_parent(object);
00188 
00189         if(parent == NULL)
00190                 return;
00191         
00192         guint n_objects, i;
00193         GParamSpec *prop;
00194         gchar *name, *value;
00195         MidgardObjectClass *klass = MIDGARD_OBJECT_GET_CLASS(parent);
00196         gchar *primary = midgard_object_class_get_primary_property(klass);
00197         
00198         MidgardQueryBuilder *builder = 
00199                 midgard_query_builder_new(parent->mgd, "midgard_element");
00200 
00201         if(!builder) {
00202                 MIDGARD_ERRNO_SET(parent->mgd, MGD_ERR_INTERNAL);
00203                 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG,
00204                                 "Invalid query builder configuration (%s)",
00205                                 G_OBJECT_TYPE_NAME(G_OBJECT(parent)));
00206                 return;
00207         }
00208 
00209         /* Find object's primary property */
00210         prop = g_object_class_find_property(
00211                         G_OBJECT_GET_CLASS(G_OBJECT(parent)), primary);
00212         
00213         GValue pval = {0,};
00214         /* Initialize primary property value */
00215         g_value_init(&pval,prop->value_type);
00216         g_object_get_property(G_OBJECT(object), primary, &pval);
00217         /* I think we can hardcode parent property */
00218         midgard_query_builder_add_constraint(builder, "style", "=", &pval);
00219         g_value_unset(&pval);
00220 
00221         GObject **childs = 
00222                 midgard_query_builder_execute(builder, n_objects);
00223 
00224         for(i = 0; i < n_objects; i++){
00225                 
00226                 g_object_get(G_OBJECT(childs[i]), 
00227                                         "name", &name, 
00228                                         "value", &value,
00229                                         NULL);
00230                 g_hash_table_insert(table,
00231                                 g_strdup(name), g_strdup(value));
00232                 g_object_unref(childs[i]);              
00233         }
00234         midgard_query_builder_free(builder);
00235 
00236         /* Walk to root page */
00237         _get_parent_page_elements(parent, table);
00238         
00239         g_object_unref(parent); 
00240 }
00241 
00242 
00243 GHashTable *_style_get_elements_from_db(midgard *mgd, const gchar *path)
00244 {
00245         g_assert(mgd != NULL);
00246 
00247         gchar *spltd = g_strsplit(path, "/", -1);
00248         guint n_objects, i = 0;
00249         GHashTable *table = midgard_hash_strings_new();
00250 
00251         MgdObject *style = midgard_object_get_by_path(mgd, "midgard_style", path);
00252 
00253         /* Get all style elements */
00254         MgdObject **childs = midgard_object_list_childs(object, "midgard_element", &n_objects);
00255         
00256         if(childs != NULL) {
00257                 for(i = 0; i < n_objects; i++){
00258                         
00259                         g_object_get(G_OBJECT(childs[i]),
00260                                         "name", &name,
00261                                         "value", &value,
00262                                         NULL);
00263                         g_hash_table_insert(table, g_strdup(name), g_strdup(value));
00264                         g_object_unref(childs[i]);
00265                 }
00266         }
00267 
00268         _get_parent_style_elements(style, table);
00269         g_object_unref(style);
00270         return table;
00271 }
00272 
00273 
00274 /* Registers style in Midgard internal styles' stack. */
00275 gboolean midgard_style_register(midgard *mgd, const gchar *path, MgdStyle *style)
00276 {
00277         g_assert(mgd != NULL);
00278         g_assert(style != NULL);
00279 
00280         gchar **spltd;
00281         GHashTable *table;
00282 
00283         /* Database style , prefix mgd:// */
00284         if(g_str_has_prefix(path, "mgd://")){
00285 
00286                 spltd = g_strsplit(path, "mgd://", 2);
00287                 _style_get_elements_from_db(mgd, (const gchar *)spltd[1]);
00288                 g_strfreev(spltd);
00289 
00290         /* File system style , get files */     
00291         } else if(g_str_has_prefix(path, "file://")) {
00292 
00293                 spltd = g_strsplit(path, "file://", 2);
00294                 _style_get_elements_from_dir(mgd, (const gchar *)spltd[1]);
00295                 g_strfreev(spltd);
00296 
00297         /* This is default for database style */        
00298         } else if(g_str_has_prefix(path, "/")) {
00299 
00300                 _style_get_elements_from_db(mgd, (const gchar *)spltd[1]);
00301         }
00302 }
00303 
00304 /* TODO
00305  * midgard_style_list_styles(MgdStyle *style);
00306  */ 
00307 
00308 gchar *midgard_style_get_element(MgdStyle *style, const gchar *name)
00309 {
00310         g_assert(style != NULL);
00311         gchar *element;
00312 
00313         /* First we gete element from page elements */
00314         element = g_hash_table_lookup(style->page_elements, name);
00315         
00316         /* Element not found , we look for element in every style's hash */
00317         if(element == NULL) {
00318 
00319                 /* TODO , queue, stack , whatever lookup */
00320 
00321                 if(element == NULL)
00322                         element = "";
00323         }
00324         return element; 
00325 }
00326 
00327 gboolean midgard_style_is_element_loaded(MgdStyle *style, const gchar *name)
00328 {
00329         g_assert(style != NULL);
00330 
00331         /* Get element, pointer is returned so no need to free memory */
00332         if(midgard_style_get_element(style, name) != NULL)
00333                 return TRUE;
00334 
00335         /* Element not found , return FALSE */
00336         return FALSE;
00337 }
00338 
00339 void midgard_style_free(MgdStyle *style)
00340 {
00341         g_assert(style != NULL);
00342         
00343         /* TODO , free style members when defined */
00344 }

Generated on Thu Feb 22 06:15:18 2007 for midgard-core by  doxygen 1.4.6