summaryrefslogtreecommitdiff
path: root/gstudio/models.py
diff options
context:
space:
mode:
authorgnowgi <nagarjun@gnowledge.org>2012-03-15 16:19:20 +0530
committergnowgi <nagarjun@gnowledge.org>2012-03-15 16:19:20 +0530
commit7a4f561e851fdc7246d804c3abb6748b8a4199a6 (patch)
treed2afc3463fd49625a9be482012f5c3bfcf7c42b9 /gstudio/models.py
downloadgnowsys-7a4f561e851fdc7246d804c3abb6748b8a4199a6.tar.gz
master trunk of gnowsys-studio
Diffstat (limited to 'gstudio/models.py')
-rw-r--r--gstudio/models.py1772
1 files changed, 1772 insertions, 0 deletions
diff --git a/gstudio/models.py b/gstudio/models.py
new file mode 100644
index 0000000..8e42807
--- /dev/null
+++ b/gstudio/models.py
@@ -0,0 +1,1772 @@
+
+# Copyright (c) 2011, 2012 Free Software Foundation
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+# This project incorporates work covered by the following copyright and permission notice:
+
+# Copyright (c) 2009, Julien Fache
+# All rights reserved.
+
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of the author nor the names of other
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Copyright (c) 2011, 2012 Free Software Foundation
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+"""Super models of Gstudio """
+import warnings
+from datetime import datetime
+from django.db import models
+from django.db.models import Q
+from django.utils.html import strip_tags
+from django.utils.html import linebreaks
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+from django.db.models.signals import post_save
+from django.utils.importlib import import_module
+from django.contrib import comments
+from django.contrib.comments.models import CommentFlag
+from django.contrib.comments.moderation import moderator
+from django.utils.translation import ugettext_lazy as _
+from django.contrib.markup.templatetags.markup import markdown
+from django.contrib.markup.templatetags.markup import textile
+from django.contrib.markup.templatetags.markup import restructuredtext
+import mptt
+
+from djangoratings.fields import RatingField
+from tagging.fields import TagField
+from gstudio.settings import UPLOAD_TO
+from gstudio.settings import MARKUP_LANGUAGE
+from gstudio.settings import NODETYPE_TEMPLATES
+from gstudio.settings import NODETYPE_BASE_MODEL
+from gstudio.settings import MARKDOWN_EXTENSIONS
+from gstudio.settings import AUTO_CLOSE_COMMENTS_AFTER
+from gstudio.managers import nodetypes_published
+from gstudio.managers import NodetypePublishedManager
+from gstudio.managers import AuthorPublishedManager
+from gstudio.managers import DRAFT, HIDDEN, PUBLISHED
+from gstudio.moderator import NodetypeCommentModerator
+from gstudio.url_shortener import get_url_shortener
+from gstudio.signals import ping_directories_handler
+from gstudio.signals import ping_external_urls_handler
+import json
+import reversion
+from reversion.models import Version
+from django.core import serializers
+
+NODETYPE_CHOICES = (
+ ('ND', 'Nodes'),
+ ( 'OB' ,'Objects'),
+ ('ED', 'Edges'),
+ ('NT', 'Node types'),
+ ('ET', 'Edge types'),
+ ('OT', 'Object types'),
+ ('RT', 'Relation types'),
+ ('MT', 'Metatypes'),
+ ('AT', 'Attribute types'),
+ ('RN', 'Relations'),
+ ('AS', 'Attributes'),
+ ('ST', 'System type'),
+ ('SY', 'System'),
+ ('NS', 'Node specification'),
+ ('AS', 'Attribute specification'),
+ ('RS', 'Relation specification'),
+ ('IN', 'Intersection'),
+ ('CP', 'Complement'),
+ ('UN', 'Union'),
+ )
+
+DEPTYPE_CHOICES = (
+ ('0', 'Concept-Concept'),
+ ('1', 'Activity-Activity'),
+ ('2', 'Question-Question'),
+ ('3', 'Concept-Activity'),
+ ('4', 'Activity-Concept'),
+ ('5', 'Question-Concept'),
+ ('6', 'Concept-Question'),
+ ('7', 'Question-Activity'),
+ ('8', 'Activity-Question'),
+ )
+
+FIELD_TYPE_CHOICES = (
+ ('1', 'CharField'),
+ ('2', 'TextField'),
+ ('3', 'IntegerField'),
+ ('4', 'CommaSeparatedIntegerField'),
+ ('5', 'BigIntegerField'),
+ ('6', 'PositiveIntegerField'),
+ ('7', 'DecimalField'),
+ ('8', 'FloatField'),
+ ('9', 'BooleanField'),
+ ('10', 'NullBooleanField'),
+ ('11', 'DateField'),
+ ('12', 'DateTimeField'),
+ ('13', 'TimeField'),
+ ('14', 'EmailField'),
+ ('15', 'FileField'),
+ ('16', 'FilePathField'),
+ ('17', 'ImageField'),
+ ('18', 'URLField'),
+ ('19', 'IPAddressField'),
+ )
+
+
+STATUS_CHOICES = ((DRAFT, _('draft')),
+ (HIDDEN, _('hidden')),
+ (PUBLISHED, _('published')))
+
+class Author(User):
+ """Proxy Model around User"""
+
+ objects = models.Manager()
+ published = AuthorPublishedManager()
+
+ def nodetypes_published(self):
+ """Return only the nodetypes published"""
+ return nodetypes_published(self.nodetypes)
+
+ @property
+ def title(self):
+ return self.username
+
+ @models.permalink
+ def get_absolute_url(self):
+ """Return author's URL"""
+ #return "/authors/%s/" %(self.username)
+ return ('gstudio_author_detail', (self.username,))
+
+ class Meta:
+ """Author's Meta"""
+ proxy = True
+
+class NID(models.Model):
+ """the set of all nodes. provides node ID (NID) to all nodes in
+ the network, including edges. Edges are also first class citizens
+ in the gnowledge base. """
+
+ title = models.CharField(_('title'), help_text=_('give a name to the node'), max_length=255)
+ last_update = models.DateTimeField(_('last update'), default=datetime.now)
+ creation_date = models.DateTimeField(_('creation date'),
+ default=datetime.now)
+
+ slug = models.SlugField(help_text=_('used for publication'),
+ unique_for_date='creation_date',
+ max_length=255)
+
+
+ def get_serialized_dict(self):
+ """
+ return the fields in a serialized form of the current object using the __dict__ function.
+ """
+ return self.__dict__
+
+ @models.permalink
+ def get_absolute_url(self):
+ """Return nodetype's URL"""
+
+ return ('gstudio_nodetype_detail', (), {
+ 'year': self.creation_date.strftime('%Y'),
+ 'month': self.creation_date.strftime('%m'),
+ 'day': self.creation_date.strftime('%d'),
+ 'slug': self.slug})
+
+ @property
+ def ref(self):
+ """
+ Returns the object reference the id belongs to.
+ """
+ try:
+ """
+ ALGO: get object id, go to version model, return for the given id.
+ """
+
+ # Retrieving only the relevant tupleset for the versioned objects
+ vrs = Version.objects.filter(type=0 , object_id=self.id)
+ # Returned value is a list, so splice it.
+ vrs = vrs[0]
+ except:
+ return None
+
+ return vrs.object
+
+ @property
+ def get_edit_url(self):
+ return "/admin/" + self._meta.app_label + "/" + self._meta.module_name + "/" + str(self.id)
+
+
+
+ def get_serialized_data(self):
+ """
+ return the fields in a serialized form of the current object.
+ get object id, go to version model, return serialized_data for the given id
+ """
+ from reversion.models import Version
+ version = Version.objects.get(id=self.id)
+ return version.serialized_data
+
+ def __unicode__(self):
+ return self.title
+
+
+ class Meta:
+ """NID's Meta"""
+
+
+
+class Node(NID):
+ """
+ Super class
+ """
+
+ altnames = TagField(_('alternate names'), help_text=_('alternate names if any'), blank=True, null=True)
+ plural = models.CharField(_('plural name'), help_text=_('plural form of the node name if any'), max_length=255, blank=True, null=True)
+ rating = RatingField(range=5, can_change_vote = True, help_text=_('your rating'), blank=True, null=True)
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ abstract=False
+
+class Edge(NID):
+
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ abstract=False
+
+
+class Metatype(Node):
+ """
+ Metatype object for Nodetype
+ """
+
+
+ description = models.TextField(_('description'), blank=True, null=True)
+ parent = models.ForeignKey('self', null=True, blank=True, verbose_name=_('parent metatype'), related_name='children')
+
+
+ def nodetypes_published(self):
+ """
+ Return only the published nodetypes
+ """
+ return nodetypes_published(self.member_types)
+
+ @property
+ def get_nbh(self):
+ """
+ Returns the neighbourhood of the metatype
+ """
+ nbh = {}
+ nbh['title'] = self.title
+ nbh['altnames'] = self.altnames
+ nbh['plural'] = self.plural
+
+ if self.parent:
+ nbh['typeof'] = self.parent
+ # generate ids and names of children/members
+ nbh['contains_subtypes'] = self.children.get_query_set()
+ nbh['contains_members'] = self.nodetypes.all()
+ nbh['left_subjecttype_of'] = Relationtype.objects.filter(left_subjecttype=self.id)
+ nbh['right_subjecttype_of'] = Relationtype.objects.filter(right_subjecttype=self.id)
+ nbh['attributetypes'] = Attributetype.objects.filter(subjecttype=self.id)
+
+ return nbh
+
+
+ @property
+ def get_possible_attributetypes(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the AT's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # recursive thru parent field and append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ attrtypes = []
+
+ for each in ancestor_list:
+ # retrieve all the AT's from each ancestor
+ attrtypes.extend(Attributetype.objects.filter(subjecttype=each.id))
+
+ return attrtypes
+
+
+ @property
+ def get_possible_rels(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the R's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ rels = {}
+ rt_set = Relation.objects.all()
+ right_subset = []
+ left_subset = []
+
+ for each in ancestor_list:
+ # retrieve all the RT's from each ancestor
+ right_subset.extend(rt_set.filter(subject1=each.id))
+ left_subset.extend(rt_set.filter(subject2=each.id))
+
+ rels['possible_leftroles'] = left_subset
+ rels['possible_rightroles'] = right_subset
+
+ return rels
+
+
+
+ @property
+ def get_possible_attributes(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the RT's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # recursive thru parent field and append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ attrs = []
+
+ for each in ancestor_list:
+ # retrieve all the AT's from each ancestor
+ attrs.extend(Attribute.objects.filter(subject=each.id))
+
+ return attrs
+
+ @property
+ def get_rendered_nbh(self):
+ """
+ Returns the neighbourhood of the metatype
+ """
+ nbh = {}
+ nbh['title'] = self.title
+ nbh['altnames'] = self.altnames
+ nbh['plural'] = self.plural
+
+ if self.parent:
+ nbh['typeof'] = self.parent
+ # generate ids and names of children
+ nbh['contains_subtypes'] = self.children.get_query_set()
+ contains_members_list = []
+ for each in self.nodetypes.all():
+ contains_members_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['contains_members'] = contains_members_list
+ nbh['left_subjecttype_of'] = Relationtype.objects.filter(left_subjecttype=self.id)
+ nbh['right_subjecttype_of'] = Relationtype.objects.filter(right_subjecttype=self.id)
+ nbh['attributetypes'] = Attributetype.objects.filter(subjecttype=self.id)
+
+
+ return nbh
+
+
+ @property
+ def tree_path(self):
+ """Return metatype's tree path, by its ancestors"""
+ if self.parent:
+ return '%s/%s' % (self.parent.tree_path, self.slug)
+ return self.slug
+
+ def __unicode__(self):
+ return self.title
+
+ @property
+ def composed_sentence(self):
+ "composes the relation as a sentence in triple format."
+ if self.parent:
+ return '%s is a kind of %s' % (self.title, self.parent.tree_path)
+ return '%s is a root node' % (self.slug)
+
+
+ @models.permalink
+ def get_absolute_url(self):
+ """Return metatype's URL"""
+ return ('gstudio_metatype_detail', (self.tree_path,))
+
+
+ class Meta:
+ """Metatype's Meta"""
+ ordering = ['title']
+ verbose_name = _('metatype')
+ verbose_name_plural = _('metatypes')
+
+
+
+
+
+class Nodetype(Node):
+ """
+ Model design for publishing nodetypes. Other nodetypes inherit this class.
+ """
+
+
+
+ STATUS_CHOICES = ((DRAFT, _('draft')),
+ (HIDDEN, _('hidden')),
+ (PUBLISHED, _('published')))
+
+ content = models.TextField(_('content'), null=True, blank=True)
+ parent = models.ForeignKey('self', null=True, blank=True,
+ verbose_name=_('is a kind of'),
+ related_name='children')
+
+ prior_nodes = models.ManyToManyField('self', null=True, blank=True,
+ verbose_name=_('its meaning depends on '),
+ related_name='posterior_nodes')
+ posterior_nodes = models.ManyToManyField('self', null=True, blank=True,
+ verbose_name=_('required for the meaning of '),
+ related_name='prior_nodes')
+
+ image = models.ImageField(_('image'), upload_to=UPLOAD_TO,
+ blank=True, help_text=_('used for illustration'))
+
+ excerpt = models.TextField(_('excerpt'), blank=True,
+ help_text=_('optional element'))
+
+ tags = TagField(_('tags'))
+ metatypes = models.ManyToManyField(Metatype, verbose_name=_('member of metatypes'),
+ related_name='member_types',
+ blank=True, null=True)
+
+
+
+ authors = models.ManyToManyField(User, verbose_name=_('authors'),
+ related_name='nodetypes',
+ blank=True, null=False)
+
+ status = models.IntegerField(choices=STATUS_CHOICES, default=PUBLISHED)
+
+ featured = models.BooleanField(_('featured'), default=False)
+ comment_enabled = models.BooleanField(_('comment enabled'), default=True)
+ pingback_enabled = models.BooleanField(_('linkback enabled'), default=True)
+
+
+
+ start_publication = models.DateTimeField(_('start publication'),
+ help_text=_('date start publish'),
+ default=datetime.now)
+ end_publication = models.DateTimeField(_('end publication'),
+ help_text=_('date end publish'),
+ default=datetime(2042, 3, 15))
+
+ sites = models.ManyToManyField(Site, verbose_name=_('sites publication'),
+ related_name='nodetypes')
+
+ login_required = models.BooleanField(
+ _('login required'), default=False,
+ help_text=_('only authenticated users can view the nodetype'))
+ password = models.CharField(
+ _('password'), max_length=50, blank=True,
+ help_text=_('protect the nodetype with a password'))
+
+ template = models.CharField(
+ _('template'), max_length=250,
+ default='gstudio/nodetype_detail.html',
+ choices=[('gstudio/nodetype_detail.html', _('Default template'))] + \
+ NODETYPE_TEMPLATES,
+ help_text=_('template used to display the nodetype'))
+
+ objects = models.Manager()
+ published = NodetypePublishedManager()
+
+
+ def get_possible_reltypes(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the RT's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ reltypes = {}
+ rt_set = Relationtype.objects.all()
+ right_subset = []
+ left_subset = []
+
+ for each in ancestor_list:
+ # retrieve all the RT's from each ancestor
+ right_subset.extend(rt_set.filter(subjecttypeLeft=each.id))
+ left_subset.extend(rt_set.filter(subjecttypeRight=each.id))
+
+ reltypes['possible_leftroles'] = left_subset
+ reltypes['possible_rightroles'] = right_subset
+
+ return reltypes
+
+
+ @property
+ def get_possible_attributetypes(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the AT's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # recursive thru parent field and append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ attrtypes = []
+
+ for each in ancestor_list:
+ # retrieve all the AT's from each ancestor
+ attrtypes.extend(Attributetype.objects.filter(subjecttype=each.id))
+
+ return attrtypes
+
+
+ @property
+ def get_possible_rels(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the R's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ rels = {}
+ rt_set = Relation.objects.all()
+ right_subset = []
+ left_subset = []
+
+ for each in ancestor_list:
+ # retrieve all the RT's from each ancestor
+ right_subset.extend(rt_set.filter(subject1=each.id))
+ left_subset.extend(rt_set.filter(subject2=each.id))
+
+ rels['possible_leftroles'] = left_subset
+ rels['possible_rightroles'] = right_subset
+
+ return rels
+
+
+
+ @property
+ def get_possible_attributes(self):
+ """
+ Gets the relations possible for this metatype
+ 1. Recursively create a set of all the ancestors i.e. parent/subtypes of the MT.
+ 2. Get all the RT's linked to each ancestor
+ """
+ #Step 1.
+ ancestor_list = []
+ this_parent = self.parent
+
+ # recursive thru parent field and append
+ while this_parent:
+ ancestor_list.append(this_parent)
+ this_parent = this_parent.parent
+
+ #Step 2.
+ attrs = []
+
+ for each in ancestor_list:
+ # retrieve all the AT's from each ancestor
+ attrs.extend(Attribute.objects.filter(subject=each.id))
+
+ return attrs
+
+ def get_graph_json(self):
+
+ predicate_id={"plural":"a1","altnames":"a2","contains_members":"a3","contains_subtypes":"a4"}
+ g_json = {}
+ g_json["node_metadata"]= []
+
+
+ nbh = self.get_nbh
+
+ this_node = {"_id":str(self.id),"title":self.title,"screen_name":self.title, "url":self.get_absolute_url()}
+ for key in predicate_id.keys():
+ if nbh[key]:
+ try:
+ g_json[str(key)]=[]
+ g_json["node_metadata"].append({"_id":str(predicate_id[key]),"screen_name":key})
+ g_json[str(key)].append({"from":self.id , "to":predicate_id[key],"value":1 })
+ if not isinstance(nbh[key],basestring):
+ for item in nbh[key]:
+
+ g_json["node_metadata"].append({"_id":str(item.id),"screen_name":item.title, "title":item.title, "url":item.get_absolute_url()})
+ g_json[str(key)].append({"from":predicate_id[key] , "to":item.id ,"value":1 })
+
+ else:
+ value={nbh["plural"]:"a4",nbh["altnames"]:"a5"}
+ this_node[str(key)]=nbh[key]
+
+ for item in value.keys():
+ g_json["node_metadata"].append({"_id":str(value[nbh[key]]),"screen_name":nbh[key]})
+ g_json[str(key)].append({"from":predicate_id[key] , "to":value[nbh[key]] ,"value":1 })
+
+
+ except:
+ pass
+ g_json["node_metadata"].append(this_node)
+ return json.dumps(g_json)
+
+
+ @property
+ def tree_path(self):
+ """Return nodetype's tree path, by its ancestors"""
+ if self.parent:
+ return '%s/%s' % (self.parent.tree_path, self.slug)
+ return self.slug
+
+ @property
+ def tree_path_sentence(self):
+ """ Return the parent of the nodetype in a triple form """
+ if self.parent:
+ return '%s is a kind of %s' % (self.title, self.parent.tree_path)
+ return '%s is a root node' % (self.title)
+
+
+ @property
+ def html_content(self):
+ """Return the content correctly formatted"""
+ if MARKUP_LANGUAGE == 'markdown':
+ return markdown(self.content, MARKDOWN_EXTENSIONS)
+ elif MARKUP_LANGUAGE == 'textile':
+ return textile(self.content)
+ elif MARKUP_LANGUAGE == 'restructuredtext':
+ return restructuredtext(self.content)
+ elif not '</p>' in self.content:
+ return linebreaks(self.content)
+ return self.content
+ @property
+ def get_relations(self):
+ """
+ Returns all the relations of the nodetype
+ """
+ relations={}
+
+ left_relations=Relation.objects.filter(left_subject=self.id)
+ if left_relations:
+ for each in left_relations:
+ relation=each.relationtype.title
+ predicate=each.right_subject
+ relations[relation]=predicate
+
+ right_relations=Relation.objects.filter(right_subject=self.id)
+ if right_relations:
+ for each in right_relations:
+ relation=each.relationtype.inverse
+ predicate=each.left_subject
+ relations[relation]=predicate
+ return relations
+
+ @property
+ def get_rendered_nbh(self):
+ """
+ Returns the neighbourhood of the nodetype
+ """
+ nbh = {}
+ nbh['title'] = self.title
+ nbh['altnames'] = self.altnames
+ nbh['plural'] = self.plural
+ #get all MTs
+ member_of_dict = {}
+ for each in self.metatypes.all():
+ member_of_dict[each.title]= each.get_absolute_url()
+ nbh['member_of_metatypes']=member_of_dict
+ typeof={}
+ parent=self.parent
+ if parent:
+ typeof[parent] = parent.get_absolute_url()
+ nbh['type_of']=typeof
+ #get all subtypes
+ subtypes={}
+ for each in Nodetype.objects.filter(parent=self.id):
+ subtypes[each.title] =each.get_absolute_url()
+ nbh['contains_subtypes']=subtypes
+ # get all the objects inheriting this OT
+ contains_members_dict = {}
+ for each in self.member_objects.all():
+ contains_members_dict[each.title]= each.get_absolute_url()
+ nbh['contains_members'] = contains_members_dict
+ #get prior nodes
+ priornodes_dict = {}
+ for each in self.prior_nodes.all():
+ priornodes_dict[each.title]= each.get_absolute_url()
+ nbh['priornodes'] = priornodes_dict
+ #get posterior nodes
+ posteriornodes_dict = {}
+ for each in self.posterior_nodes.all():
+ posteriornodes_dict[each.title]= each.get_absolute_url()
+ nbh['posteriornodes'] = posteriornodes_dict
+ #get authors
+ author_dict = {}
+ for each in self.authors.all():
+ author_dict['User'] = each.get_absolute_url()
+ nbh['authors'] = author_dict
+ #get siblings
+ siblings={}
+ for each in self.get_siblings():
+ siblings[each.title]=each.get_absolute_url()
+ nbh['siblings']=siblings
+ #get Relations
+ relns={}
+ relnvalue={}
+ if self.get_relations:
+ NTrelns=self.get_relations
+ for value in NTrelns:
+ relnvalue[NTrelns[value].title]=NTrelns[value].ref.get_absolute_url()
+ relns[value]=relnvalue
+ nbh['relations']=relns
+ #get Attributes
+ attributes = self.subject_of.all()
+ nbh['attributes']=attributes
+ #get ATs
+ attributetypes={}
+ for each in self.subjecttype_of.all():
+ attributetypes[each.title]=each.get_absolute_url()
+ nbh['ats']=attributetypes
+ #get RTs as leftroles and rightroles
+ leftroles = {}
+ for each in self.left_subjecttype_of.all():
+ leftroles[each.title]=each.get_absolute_url()
+ nbh['leftroles']=leftroles
+ rightroles = {}
+ for each in self.right_subjecttype_of.all():
+ rightroles[each.title]=each.get_absolute_url()
+ nbh['rightroles']=rightroles
+ return nbh
+
+
+ @property
+ def previous_nodetype(self):
+ """Return the previous nodetype"""
+ nodetypes = Nodetype.published.filter(
+ creation_date__lt=self.creation_date)[:1]
+ if nodetypes:
+ return nodetypes[0]
+
+ @property
+ def next_nodetype(self):
+ """Return the next nodetype"""
+ nodetypes = Nodetype.published.filter(
+ creation_date__gt=self.creation_date).order_by('creation_date')[:1]
+ if nodetypes:
+ return nodetypes[0]
+
+ @property
+ def word_count(self):
+ """Count the words of a nodetype"""
+ return len(strip_tags(self.html_content).split())
+
+ @property
+ def is_actual(self):
+ """Check if a nodetype is within publication period"""
+ now = datetime.now()
+ return now >= self.start_publication and now < self.end_publication
+
+ @property
+ def is_visible(self):
+ """Check if a nodetype is visible on site"""
+ return self.is_actual and self.status == PUBLISHED
+
+ @property
+ def related_published(self):
+ """Return only related nodetypes published"""
+ return nodetypes_published(self.related)
+
+ @property
+ def discussions(self):
+ """Return published discussions"""
+ return comments.get_model().objects.for_model(
+ self).filter(is_public=True)
+
+ @property
+ def comments(self):
+ """Return published comments"""
+ return self.discussions.filter(Q(flags=None) | Q(
+ flags__flag=CommentFlag.MODERATOR_APPROVAL))
+
+ @property
+ def pingbacks(self):
+ """Return published pingbacks"""
+ return self.discussions.filter(flags__flag='pingback')
+
+ @property
+ def trackbacks(self):
+ """Return published trackbacks"""
+ return self.discussions.filter(flags__flag='trackback')
+
+ @property
+ def comments_are_open(self):
+ """Check if comments are open"""
+ if AUTO_CLOSE_COMMENTS_AFTER and self.comment_enabled:
+ return (datetime.now() - self.start_publication).days < \
+ AUTO_CLOSE_COMMENTS_AFTER
+ return self.comment_enabled
+
+ @property
+ def short_url(self):
+ """Return the nodetype's short url"""
+ return get_url_shortener()(self)
+
+ def __unicode__(self):
+ return self.title
+
+ @property
+ def memberof_sentence(self):
+ """Return the metatype of which the nodetype is a member of"""
+
+ if self.metatypes.count:
+ for each in self.metatypes.all():
+ return '%s is a member of metatype %s' % (self.title, each)
+ return '%s is not a fully defined name, consider making it a member of a suitable metatype' % (self.title)
+
+
+ @property
+ def subtypeof_sentence(self):
+ "composes the relation as a sentence in triple format."
+ if self.parent:
+ return '%s is a subtype of %s' % (self.title, self.parent.tree_path)
+ return '%s is a root node' % (self.title)
+ composed_sentence = property(subtypeof_sentence)
+
+ def subtypeof(self):
+ "retuns the parent nodetype."
+ if self.parent:
+ return '%s' % (self.parent.tree_path)
+ return None
+
+ @models.permalink
+ def get_absolute_url(self):
+ """Return nodetype's URL"""
+ return ('gstudio_nodetype_detail', (), {
+ 'year': self.creation_date.strftime('%Y'),
+ 'month': self.creation_date.strftime('%m'),
+ 'day': self.creation_date.strftime('%d'),
+ 'slug': self.slug})
+
+ def get_serialized_data(self):
+ """
+ return the fields in a serialized form of the current object.
+ get object id, go to version model, return serialized_data for the given id
+ """
+ from reversion.models import Version
+ version = Version.objects.get(id=self.node_ptr_id)
+ return version.serialized_data
+
+ class Meta:
+ """Nodetype's Meta"""
+ ordering = ['-creation_date']
+ verbose_name = _('node type')
+ verbose_name_plural = _('node types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class Objecttype(Nodetype):
+ '''
+ Object class
+ '''
+
+ def __unicode__(self):
+ return self.title
+
+ #def get_graph_json(self):
+
+
+
+
+ @property
+ def get_attributetypes(self):
+ return self.subjecttype_of.all()
+
+ @property
+ def get_relationtypes(self):
+
+ left_relset = self.left_subjecttype_of.all()
+ right_relset = self.right_subjecttype_of.all()
+
+ reltypes = {}
+ reltypes['left_subjecttype_of']=left_relset
+ reltypes['right_subjecttype_of']=right_relset
+ return reltypes
+
+ @property
+ def get_left_subjecttypes(self):
+ """
+ for which relation types does this object become a domain of any relation type
+ """
+ reltypes = []
+ left_relset = self.left_subjecttype_of.all()
+ for relationtype in left_relset:
+ reltypes.append(relationtype)
+ return reltypes
+
+ @property
+ def get_rightroles(self):
+ """
+ for which relation types does this object become a domain of any relation type
+ """
+ reltypes = []
+ right_relset = self.right_subjecttype_of.all()
+ for relationtype in right_relset:
+ reltypes.append(relationtype)
+ return reltypes
+
+ @property
+ def get_subjecttypes(self):
+ """
+ for which relation types does this object become a domain of any relation type
+ """
+ subjecttypes = []
+ attrset = self.subjecttype_of.all()
+ for subjecttype in attrset:
+ subjecttypes.append(subjecttype)
+ return subjecttypes
+
+
+ @property
+ def member_of_metatypes(self):
+ """
+ returns if the objecttype is a member of the membership in a metatype class
+ """
+ types = []
+ if self.metatypes.all():
+ for metatype in self.metatypes.all():
+ types.append(metatype.title)
+ return types
+
+
+ @property
+ def get_members(self):
+ """
+ get members of the object type
+ """
+ members = []
+ if self.member_objects.all():
+ for gbobject in self.member_objects.all():
+ members.append(gbobject)
+ return members
+
+ @property
+ def get_nbh(self):
+ """
+ Returns the neighbourhood of the nodetype
+ """
+ nbh = {}
+ nbh['title'] = self.title
+ nbh['altnames'] = self.altnames
+ nbh['plural'] = self.plural
+ nbh['member_of_metatype'] = self.metatypes.all()
+ # get all the ATs for the objecttype
+ nbh['subjecttype_of']= self.subjecttype_of.all()
+ # get all the RTs for the objecttype
+ nbh.update(self.get_relationtypes)
+
+ nbh['type_of'] = [self.parent]
+
+ nbh['contains_subtypes'] = Nodetype.objects.filter(parent=self.id)
+ # get all the objects inheriting this OT
+ nbh['contains_members'] = self.member_objects.all()
+
+ nbh['prior_nodes'] = self.prior_nodes.all()
+
+ nbh['posterior_nodes'] = self.posterior_nodes.all()
+
+ nbh['authors'] = self.authors.all()
+
+ return nbh
+
+ @property
+ def get_rendered_nbh(self):
+ """
+ Returns the neighbourhood of the nodetype with the hyperlinks of nodes rendered
+ """
+ nbh = {}
+ nbh['title'] = self.title
+ nbh['altnames'] = self.altnames
+ nbh['plural'] = self.plural
+ member_of_metatypes_list = []
+ for each in self.metatypes.all():
+ member_of_metatypes_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['member_of_metatypes'] = member_of_metatypes_list
+
+
+ attributetypes_list = []
+ for each in self.get_attributetypes:
+ attributetypes_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['attributetypes'] = attributetypes_list
+
+
+ # get all the RTs for the objecttype
+ reltypes_list = []
+ for each in self.get_relationtypes:
+ reltypes_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['relationtypes'] = reltypes_list
+
+ nbh['type_of'] = self.parent
+
+ nbh['contains_subtypes'] = Nodetype.objects.filter(parent=self.id)
+ # get all the objects inheriting this OT
+ contains_members_list = []
+ for each in self.gbobjects.all():
+ contains_members_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['contains_members'] = contains_members_list
+
+ prior_nodes_list = []
+ for each in self.prior_nodes.all():
+ prior_nodes_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['prior_nodes'] = prior_nodes_list
+
+ posterior_nodes_list = []
+ for each in self.posterior_nodes.all():
+ posterior_nodes_list.append('<a href="%s">%s</a>' % (each.get_absolute_url(), each.title))
+ nbh['posterior_nodes'] = posterior_nodes_list
+
+ author_list = []
+ for each in self.authors.all():
+ author_list.append('<a href="%s"></a>' % (each.get_absolute_url()))
+ nbh['authors'] = author_list
+ return nbh
+
+
+
+ class Meta:
+ """
+ object type's meta class
+ """
+ verbose_name = _('object type')
+ verbose_name_plural = _('object types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+
+
+class Relationtype(Nodetype):
+ '''
+ Properties with left and right subjects (Binary relations) are defined in this class.
+ '''
+ inverse = models.CharField(_('inverse name'), help_text=_('when subjecttypes are interchanged, what should be the name of the relation type? This is mandatory field. If the relation is symmetric, same name will do.'), max_length=255,db_index=True )
+ left_subjecttype = models.ForeignKey(NID,related_name="left_subjecttype_of", verbose_name='left role')
+ left_applicable_nodetypes = models.CharField(max_length=2,choices=NODETYPE_CHOICES,default='OT', verbose_name='Node types for left role')
+ left_cardinality = models.IntegerField(null=True, blank=True, verbose_name='cardinality for the left role')
+ right_subjecttype = models.ForeignKey(NID,related_name="right_subjecttype_of", verbose_name='right role')
+ right_applicable_nodetypes = models.CharField(max_length=2,choices=NODETYPE_CHOICES,default='OT', verbose_name='Node types for right role')
+ right_cardinality = models.IntegerField(null=True, blank=True, verbose_name='cardinality for the right role')
+ is_symmetrical = models.NullBooleanField(verbose_name='Is symmetrical?')
+ is_reflexive = models.NullBooleanField(verbose_name='Is reflexive?')
+ is_transitive = models.NullBooleanField(verbose_name='Is transitive?')
+
+
+ def get_serialized_data(self):
+ """
+ return the fields in a serialized form of the current object.
+ get object id, go to version model, return serialized_data for the given id
+ """
+ from reversion.models import Version
+ version = Version.objects.get(id=self.node_ptr_id)
+ return version.serialized_data
+
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ """
+ relation type's meta class
+ """
+ verbose_name = _('relation type')
+ verbose_name_plural = _('relation types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class Attributetype(Nodetype):
+ '''
+ To define attributes of objects. First three fields are mandatory.
+ The rest of the fields may be required depending on what type of
+ field is selected for datatype.
+ '''
+ subjecttype = models.ForeignKey(NID, related_name="subjecttype_of", verbose_name='subject type name')
+ applicable_nodetypes = models.CharField(max_length=2,choices=NODETYPE_CHOICES,default='OT', verbose_name='applicable nodetypes')
+ dataType = models.CharField(max_length=2, choices=FIELD_TYPE_CHOICES,default='01', verbose_name='data type of value')
+
+ verbose_name = models.CharField(max_length=500, null=True, blank=True, verbose_name='verbosename', help_text='verbose name')
+ null = models.NullBooleanField(verbose_name='Null', help_text='can the value be null?')
+ blank = models.NullBooleanField(verbose_name='Blank', help_text='can the form be left blank?')
+ help_text = models.CharField(max_length=500, null=True, blank=True, verbose_name='Help text', help_text='help text for the field')
+ max_digits = models.IntegerField(max_length=5, null=True, blank=True, verbose_name='Max digit', help_text='If you have selected Decimal Field for datatype, you have to specify the number of digits.')
+ decimal_places = models.IntegerField(max_length=2, null=True, blank=True, verbose_name='Decimal places', help_text='If you have selected Decimal Field for datatype, you have to specify the decimal places.')
+ auto_now = models.NullBooleanField(verbose_name='Auto now', null=True, blank=True, help_text='Use this if DateTime & Time Field was chosen above for datatype')
+ auto_now_add = models.NullBooleanField(verbose_name='Auto now add', null=True, blank=True, help_text='Use this if DateTime & Time Field was chosen above for datatype')
+ upload_to = models.CharField(max_length=500,verbose_name='Upload to', null=True, blank=True, help_text='Required for FileField and ImageField')
+ path=models.CharField(max_length=500,verbose_name='Path', null=True, blank=True, help_text='Required for FilePathField')
+ verify_exists=models.NullBooleanField(verbose_name='Verify exits', null=True, blank=True, help_text='Required for AttributeURLField')
+ min_length=models.IntegerField(max_length=10,null=True, blank=True, verbose_name='min length', help_text='minimum length')
+ required=models.NullBooleanField(verbose_name='required', null=True, blank=True, help_text='Use this for setting mandatory and optional fields')
+ label=models.CharField(max_length=500, null=True,blank=True,verbose_name='label',help_text='specify the "human-friendly" label')
+ unique=models.NullBooleanField(verbose_name='unique', null=True, blank=True, help_text='If True, this field must be unique throughout the table')
+ validators=models.ManyToManyField('self', verbose_name='validators',blank=True, null=True,help_text='A list of validators to run for this field')
+ default=models.CharField(max_length=500, null=True, blank=True, verbose_name='default', help_text='The default value for the field')
+ editable=models.NullBooleanField(verbose_name='required', null=True, blank=True, help_text='If False, the field will not be editable')
+
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ """
+ attribute type's meta class
+ """
+ verbose_name = _('attribute type')
+ verbose_name_plural = _('attribute types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+
+class Relation(Edge):
+ '''
+ Relations, instances of relationtypes
+ '''
+
+ left_subject_scope = models.CharField(max_length=50, verbose_name='subject scope or qualification', null=True, blank=True)
+ left_subject = models.ForeignKey(NID, related_name="left_subject_of", verbose_name='subject name')
+ relationtype_scope = models.CharField(max_length=50, verbose_name='relation scope or qualification', null=True, blank=True)
+ relationtype = models.ForeignKey(Relationtype, verbose_name='relation name')
+ right_subject_scope = models.CharField(max_length=50, verbose_name='object scope or qualification', null=True, blank=True)
+ right_subject = models.ForeignKey(NID, related_name="right_subject_of", verbose_name='object name')
+
+ def ApplicableNodeTypes_filter(self,choice):
+
+ nodeslist = []
+
+ if choice == 'ED':
+ nodeslist = Edge.objects.all()
+ if choice == 'OB':
+ nodeslist = Objects.objects.all()
+ if choice == 'ND':
+ nodeslist = Node.objects.all()
+ if choice == 'NT':
+ nodeslist = Nodetype.objects.all()
+ if choice == 'OT':
+ nodeslist = Objecttype.objects.all()
+ if choice == 'RT':
+ nodeslist = Relationtype.objects.all()
+ if choice == 'MT':
+ nodeslist = Metatype.objects.all()
+ if choice == 'AT':
+ nodeslist = Attributetype.objects.all()
+ if choice == 'RN':
+ nodeslist = Relation.objects.all()
+ if choice == 'AS':
+ nodeslist = Attribute.objects.all()
+ if choice == 'ST':
+ nodeslist = Systemtype.objects.all()
+ if choice == 'SY':
+ nodeslist = System.objects.all()
+
+ return nodeslist
+
+
+ class Meta:
+ unique_together = (('left_subject_scope','left_subject','relationtype_scope', 'relationtype', 'right_subject_scope','right_subject'),)
+ verbose_name = _('relation')
+ verbose_name_plural = _('relations')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+ def __unicode__(self):
+ return self.composed_sentence
+
+ @property
+ def composed_sentence(self):
+ "composes the relation as a sentence in a triple format."
+ return '%s %s %s %s %s %s' % (self.left_subject_scope, self.left_subject, self.relationtype_scope, self.relationtype, self.right_subject_scope, self.right_subject)
+
+ @property
+ def inversed_sentence(self):
+ "composes the inverse relation as a sentence in a triple format."
+ return '%s %s %s %s %s' % (self.objectScope, self.right_subject, self.relationtype.inverse, self.left_subject_scope, self.left_subject )
+
+ @property
+ def key_value(self):
+ return dict({str(self.relationtype):str(self.right_subject)})
+
+ @property
+ def inverse_key_value(self):
+ return dict({str(self.relationtype.inverse):str(self.left_subject)})
+
+
+ @property
+ def relation_sentence(self):
+ """Return the relations of the objecttypes"""
+
+ if self.relationtype:
+ # for relation in self.relationtype():
+ return '%s %s %s' % (self.left_subject,self.relationtype,self.right_subject )
+
+ @property
+ def partial_composition(self):
+ '''
+ function that composes the right_subject and relation name, as in "x as a friend", "y as a sibling"
+ '''
+ return '%s as a %s' % (self.right_subject, self.relationtype)
+
+
+class Attribute(Edge):
+ '''
+ Attribute value store for default datatype varchar. Subject can be any of the
+ nodetypes.
+ '''
+
+ subject_scope = models.CharField(max_length=50, verbose_name='subject scope or qualification', null=True, blank=True)
+ subject = models.ForeignKey(NID, related_name="subject_of", verbose_name='subject name')
+ attributetype_scope = models.CharField(max_length=50, verbose_name='property scope or qualification', null=True, blank=True)
+ attributetype = models.ForeignKey(Attributetype, verbose_name='property name')
+ value_scope = models.CharField(max_length=50, verbose_name='value scope or qualification', null=True, blank=True)
+ svalue = models.CharField(max_length=100, verbose_name='serialized value')
+
+
+
+ class Meta:
+ unique_together = (('subject_scope', 'subject', 'attributetype_scope', 'attributetype', 'value_scope', 'svalue'),)
+ verbose_name = _('attribute')
+ verbose_name_plural = _('attributes')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+ def subject_filter(self,attr):
+ """
+ returns applicaable selection of nodes for selecting as subject
+ """
+ subjecttype = attr.subjecttype
+
+ for each in Objecttype.objects.all():
+ if attr.subjecttype.id == each.id:
+ return each.get_members
+
+
+
+ def __unicode__(self):
+ return self.composed_attribution
+
+ @property
+ def edge_node_dict(self):
+ '''
+ composes the attribution as a name:value pair sentence without the subject.
+ '''
+ return dict({str(self.attributetype_scope) + str(self.attributetype): str(self.value_scope)+ str(self.svalue)})
+
+ @property
+ def composed_sentence(self):
+ '''
+ composes the attribution as a sentence in a triple format.
+ '''
+ return '%s %s has %s %s %s %s' % (self.subject_scope, self.subject, self.attributetype_scope, self.attributetype, self.value_scope, self.svalue)
+
+ @property
+ def composed_attribution(self):
+ '''
+ composes a name to the attribute
+ '''
+ return 'the %s of %s is %s' % (self.attributetype, self.subject, self.svalue)
+
+ @property
+ def partial_composition(self):
+ '''
+ function that composes the value and attribute name, as in "red as color", "4 as length"
+ '''
+ return '%s as %s' % (self.svalue, self.attributetype)
+
+
+ def subject_filter(self,attr):
+ """
+ returns applicable selection of nodes for selecting objects
+ """
+ for each in Objecttype.objects.all():
+ if attr.subjecttype.id == each.id:
+ return each.get_members
+
+
+
+class AttributeCharField(Attribute):
+
+ value = models.CharField(max_length=100, verbose_name='string')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeTextField(Attribute):
+
+ value = models.TextField(verbose_name='text')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeIntegerField(Attribute):
+ value = models.IntegerField(max_length=100, verbose_name='Integer')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeCommaSeparatedIntegerField(Attribute):
+
+ value = models.CommaSeparatedIntegerField(max_length=100, verbose_name='integers separated by comma')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeBigIntegerField(Attribute):
+
+ value = models.BigIntegerField(max_length=100, verbose_name='big integer')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributePositiveIntegerField(Attribute):
+
+ value = models.PositiveIntegerField(max_length=100, verbose_name='positive integer')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeDecimalField(Attribute):
+
+ value = models.DecimalField(max_digits=3, decimal_places=2, verbose_name='decimal')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeFloatField(Attribute):
+
+ value = models.FloatField(max_length=100, verbose_name='number as float')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeBooleanField(Attribute):
+
+ value = models.BooleanField(verbose_name='boolean')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeNullBooleanField(Attribute):
+
+ value = models.NullBooleanField(verbose_name='true false or unknown')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeDateField(Attribute):
+
+ value = models.DateField(max_length=100, verbose_name='date')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeDateTimeField(Attribute):
+
+ value = models.DateTimeField(max_length=100, verbose_name='date time')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeTimeField(Attribute):
+
+ value = models.TimeField(max_length=100, verbose_name='time')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeEmailField(Attribute):
+
+ value = models.CharField(max_length=100,verbose_name='value')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeFileField(Attribute):
+
+ value = models.FileField(upload_to='/media', verbose_name='file')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeFilePathField(Attribute):
+
+ value = models.FilePathField(verbose_name='path of file')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeImageField(Attribute):
+
+ value = models.ImageField(upload_to='/media', verbose_name='image')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeURLField(Attribute):
+
+ value = models.URLField(max_length=100, verbose_name='url')
+
+ def __unicode__(self):
+ return self.title
+
+class AttributeIPAddressField(Attribute):
+
+ value = models.IPAddressField(max_length=100, verbose_name='ip address')
+
+ def __unicode__(self):
+ return self.title
+
+
+class Processtype(Nodetype):
+
+ """
+ A kind of nodetype for defining processes or events or temporal
+ objects involving change.
+ """
+ changing_attributetype_set = models.ManyToManyField(Attributetype, null=True, blank=True,
+ verbose_name=_('attribute set involved in the process'),
+ related_name=' changing_attributetype_set_of')
+ changing_relationtype_set = models.ManyToManyField(Relationtype, null=True, blank=True,
+ verbose_name=_('relation set involved in the process'),
+ related_name='changing_relationtype_set_of')
+
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ verbose_name = _('process type')
+ verbose_name_plural = _('process types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+
+
+class Systemtype(Nodetype):
+
+ """
+ class to organize Systems
+ """
+
+
+ nodetype_set = models.ManyToManyField(Nodetype, related_name="nodetype_set_of", verbose_name='Possible edges in the system',
+ blank=True, null=False)
+ relationtype_set = models.ManyToManyField(Relationtype, related_name="relationtype_set_of", verbose_name='Possible nodetypes in the system',
+ blank=True, null=False)
+ attributetype_set = models.ManyToManyField(Attributetype, related_name="attributetype_set_of", verbose_name='systems to be nested in the system',
+ blank=True, null=False)
+ metatype_set = models.ManyToManyField(Metatype, related_name="metatype_set_of", verbose_name='Possible edges in the system',
+ blank=True, null=False)
+ processtype_set = models.ManyToManyField(Processtype, related_name="processtype_set_of", verbose_name='Possible edges in the system',
+ blank=True, null=False)
+
+
+ def __unicode__(self):
+ return self.title
+
+ class Meta:
+ verbose_name = _('system type')
+ verbose_name_plural = _('system types')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class AttributeSpecification(Node):
+ """
+ specifying an attribute by a subject to say for example:
+ population of India, color of a flower etc. These do not yeild a
+ proposition but a description, which can be used as a subject in
+ another sentence.
+ """
+ attributetype = models.ForeignKey(Attributetype, verbose_name='property name')
+ subjects = models.ManyToManyField(NID, related_name="subjects_attrspec_of", verbose_name='subjects')
+
+
+ @property
+ def composed_subject(self):
+ '''
+ composes a name to the attribute
+ '''
+ subjects = u''
+ for each in self.subjects.all():
+ subjects = subjects + each.title + ' '
+ return 'the %s of %s' % (self.attributetype, subjects)
+
+
+ def __unicode__(self):
+ return self.composed_subject
+
+
+ class Meta:
+ verbose_name = _('attribute specification')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class RelationSpecification(Node):
+ """
+ specifying a relation with a subject
+ """
+ relationtype = models.ForeignKey(Relationtype, verbose_name='relation name')
+ subjects = models.ManyToManyField(NID, related_name="subjects_in_relspec", verbose_name='subjects')
+
+
+ @property
+ def composed_subject(self):
+ '''
+ composing an expression with relation name and subject
+ '''
+ subjects = u''
+ for each in self.subjects.all():
+ subjects = subjects + each.title + ' '
+ return 'the %s of %s' % (self.relationtype, subjects)
+
+ def __unicode__(self):
+ return self.composed_subject
+
+
+ class Meta:
+ verbose_name = _('relation specification')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class NodeSpecification(Node):
+ """
+ A node specified (described) by its relations or attributes or both.
+ """
+ subject = models.ForeignKey(Node, related_name="subject_nodespec", verbose_name='subject name')
+ relations = models.ManyToManyField(Relation, related_name="relations_in_nodespec", verbose_name='relations used to specify the domain')
+ attributes = models.ManyToManyField(Attribute, related_name="attributes_in_nodespec", verbose_name='attributes used to specify the domain')
+
+ @property
+ def composed_subject(self):
+ '''
+ composing an expression subject and relations
+ '''
+ relations = u''
+ for each in self.relations.all():
+ relations = relations + each.partial_composition + ', '
+ attributes = u''
+ for each in self.attributes.all():
+ attributes = attributes + each.partial_composition + ', '
+ return 'the %s with %s, %s' % (self.subject, self.relations, self.attributes)
+
+ def __unicode__(self):
+ return self.composed_subject
+
+
+ class Meta:
+ verbose_name = _('Node specification')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+class Expression(Node):
+ """
+ Expression constructor
+ """
+
+ left_term = models.ForeignKey(NID, related_name="left_term_of", verbose_name='left term name')
+ relationtype = models.ForeignKey(Relationtype, verbose_name='relation name')
+ right_term = models.ForeignKey(NID, related_name="right_term_of", verbose_name='right term name')
+
+
+ def __unicode__(self):
+ return self.composed_sentence
+
+ @property
+ def composed_sentence(self):
+ "composes the relation as a sentence in a triple format."
+ return '%s %s %s' % (self.left_term, self.relationtype, self.right_term)
+
+
+ class Meta:
+ unique_together = (('left_term','relationtype','right_term'),)
+ verbose_name = _('expression')
+ verbose_name_plural = _('expressionss')
+ permissions = (('can_view_all', 'Can view all'),
+ ('can_change_author', 'Can change author'), )
+
+
+
+class Union(Node):
+ """
+ union of two classes
+ """
+ nodetypes = models.ManyToManyField(Nodetype, related_name = 'union_of', verbose_name='node types for union')
+
+ def __unicode__(self):
+ return self.title
+
+
+
+class Complement(Node):
+ """
+ complement of a class
+ """
+ nodetypes = models.ManyToManyField(Nodetype, related_name = 'complement_of', verbose_name='complementary nodes')
+
+ def __unicode__(self):
+ return self.title
+
+class Intersection(Node):
+ """
+ Intersection of classes
+ """
+ nodetypes = models.ManyToManyField(Nodetype, related_name = 'intersection_of', verbose_name='intersection of classes')
+
+ def __unicode__(self):
+ return self.title
+
+
+reversion.register(NID)
+reversion.register(Node)
+reversion.register(Objecttype)
+reversion.register(Edge)
+
+if not reversion.is_registered(Systemtype):
+ reversion.register(Systemtype)
+
+if not reversion.is_registered(Processtype):
+ reversion.register(Processtype, follow=["changing_attributetype_set", "changing_relationtype_set"])
+
+if not reversion.is_registered(Nodetype):
+ reversion.register(Nodetype, follow=["parent", "metatypes"])
+
+if not reversion.is_registered(Metatype):
+ reversion.register(Metatype, follow=["parent"])
+
+if not reversion.is_registered(Nodetype):
+ reversion.register(Nodetype, follow=["prior_nodes", "posterior_nodes"])
+
+if not reversion.is_registered(Relationtype):
+ reversion.register(Relationtype, follow=["left_subjecttype", "right_subjecttype"])
+
+if not reversion.is_registered(Attributetype):
+ reversion.register(Attributetype, follow=["subjecttype"])
+
+if not reversion.is_registered(Attribute):
+ reversion.register(Attribute, follow=["subject", "attributetype"])
+
+if not reversion.is_registered(Relation):
+ reversion.register(Relation, follow=["left_subject", "right_subject", "relationtype"])
+
+moderator.register(Nodetype, NodetypeCommentModerator)
+mptt.register(Metatype, order_insertion_by=['title'])
+mptt.register(Nodetype, order_insertion_by=['title'])
+mptt.register(Objecttype, order_insertion_by=['title'])
+mptt.register(Relationtype, order_insertion_by=['title'])
+mptt.register(Attributetype, order_insertion_by=['title'])
+mptt.register(Systemtype, order_insertion_by=['title'])
+mptt.register(Processtype, order_insertion_by=['title'])
+post_save.connect(ping_directories_handler, sender=Nodetype,
+ dispatch_uid='gstudio.nodetype.post_save.ping_directories')
+post_save.connect(ping_external_urls_handler, sender=Nodetype,
+ dispatch_uid='gstudio.nodetype.post_save.ping_external_urls')
+
+
+