Esempio n. 1
0
    def save(self, *args, **kwargs):
        old_slug = None
        if self.pk is not None:
            old_self = Atom.objects.get(pk=self.pk)
            old_slug = old_self.slug

        super(Atom, self).save(*args, **kwargs)
        # reify any orphan relationship
        for orphan_rel in AtomOrphanRelationship.objects.filter(ref=self.slug):
            # in case it already exists (is it even possible?)
            try:
                existing_rel = AtomRelationship.objects.get(from_atom=orphan_rel.atom,
                        to_atom=self, typ=orphan_rel.typ)
            except ObjectDoesNotExist:
                reify_rel = AtomRelationship.objects.create(from_atom=orphan_rel.atom,
                    to_atom=self, typ=orphan_rel.typ)
                reify_rel.save()

            orphan_rel.delete()

        from knowledge.format import extract_references, replace_references
        # fix references when slug is changed
        if self.slug != old_slug:
            if old_slug is None or old_slug == '':
                old_ref = str(self.pk)
            else:
                old_ref = old_slug

            if self.slug is None or self.slug == '':
                new_ref = str(self.pk)
            else:
                new_ref = self.slug

            rels = AtomRelationship.objects.filter(to_atom=self)

            for rel in rels: 
                atom = rel.from_atom
                atom.text = replace_references(atom.text, old_ref, new_ref)
                atom.save()

        # extract references and test for relationships
        uptodate_rel = []
        for verb, ref in extract_references(self.text):
            try:
                reltype = AtomRelationshipType.objects.get(slug=verb)
            except ObjectDoesNotExist:
                continue
            try:
                atom = Atom.objects.by_ref(ref)
                try:
                    existing_rel = AtomRelationship.objects.get(from_atom=self,
                            to_atom=atom, typ=reltype)
                    uptodate_rel.append(existing_rel)
                except ObjectDoesNotExist:
                    arel = AtomRelationship.objects.create(from_atom=self,
                            to_atom=atom, typ=reltype)
                    arel.save()
                    uptodate_rel.append(arel)
            except ObjectDoesNotExist:
                arel = AtomOrphanRelationship.objects.create(atom=self,
                        ref=ref, typ=reltype)
                arel.save()
        extra_rel = AtomRelationship.objects.filter(from_atom=self) \
                .exclude(id__in=[ rel.id for rel in uptodate_rel ])
        for extra in extra_rel:
            extra.delete()
Esempio n. 2
0
    def clean_source(self):
        source = self.cleaned_data['source']
        # Atom bulk format
        # (% is choosen as lead symbol as it's tex comment symbol)
        # %Atom <atom type slug> 
        # %Ref [internal ref]
        # %Slug <slug>
        # %Name <name>
        # ... text ...

        lines = source.replace('\r','').split('\n')

        i = 0

        current_atom = None
        atoms = []

        for line in lines:
            if line == '':
                if current_atom is not None and current_atom['text'] != '':
                    current_atom['text'] += '\r\n'
                continue
            if line[0] == '%':
                tokens = line[1:].split()
                command = tokens[0]
                arg = line[1+len(command):].strip()

                if command.lower() == 'atom':
                    if current_atom is not None:
                        if 'ref' not in current_atom:
                            current_atom['ref'] = str(len(atoms)+1)
                        atoms.append(current_atom)
                    current_atom = { 'type' : arg, 'text' : '' }

                if command.lower() == 'ref':
                    current_atom['ref'] = arg

                if command.lower() == 'slug':
                    current_atom['slug'] = arg

                if command.lower() == 'name':
                    current_atom['name'] = arg
            elif current_atom is not None:
                current_atom['text'] += line + '\r\n'

        if current_atom is not None:
            if 'ref' not in current_atom:
                current_atom['ref'] = str(len(atoms)+1)
            atoms.append(current_atom)

        internal_refs = []
        for atom in atoms:
            internal_refs.append( atom['ref'] )

        slug_re = re.compile(r'^[\w_]+$')

        from knowledge.format import extract_references
        edges_incoming = {}
        edges_outgoing = {}

        atom_by_ref = {}
        for atom in atoms:
            atom['refs'] = extract_references(atom['text'])
            aref = atom['ref']
            atom_by_ref[aref] = atom
            edges_outgoing[aref] = []
            if aref not in edges_incoming:
                edges_incoming[aref] = []
            for _, ref in atom['refs']:
                if ref in internal_refs:
                    if ref not in edges_incoming:
                        edges_incoming[ref] = []
                    edges_incoming[ref].append(aref)
                    edges_outgoing[aref].append(ref)
                    
        s = []
        for atom in atoms:
            if edges_outgoing[atom['ref']] == []:
                s.append(atom)
            atom['outgoing'] = []


        ordered = []

        while len(s) > 0:
            a = s[0]
            ordered.append(a)
            s = s[1:]
            for oaref in edges_incoming[a['ref']]:
                edges_outgoing[oaref].remove(a['ref'])
                atom_by_ref[oaref]['outgoing'].append( a )
                if edges_outgoing[oaref] == []:
                    s.append(atom_by_ref[oaref])

        for atom in atoms:
            if edges_outgoing[atom['ref']] != []:
                raise forms.ValidationError("Cycle impliquant $%s" % atom['ref'])

        for atom in atoms:
            if 'slug' in atom and slug_re.match(atom['slug']) is None:
                raise forms.ValidationError("Slug invalide %s" % atom['slug'])

            typ = atom['type']
            if AtomType.objects.filter(slug=typ).count() == 0:
                raise forms.ValidationError("Type inconnu %s" % typ)

        self.ordered = ordered

        return source