Beispiel #1
0
class CatalogImporter:

    def __init__(self, target_doc, import_source):
        """Constructor for importer has fixed arguments"""

        self.attr_inheritance               = appconfig.get('catalog.attr_inheritance')
        self.source_path                    = import_source[0]
        self.target_doc                     = target_doc
        self.enviponment_prepeared          = self.PrepareEnvironment()
        self.DoImport()

    def DoImport(self):
        if not self.enviponment_prepeared:
            return

        if not self.InitEnvironment():
            self.target_doc.ChangeState(self.target_doc.state_importfailed)
            return

        @public.wth('Importing {0}...'.format(self.target_doc.name), self.target_doc, self.p7tpl_doc, self.pcardl_doc)
        def f():
            try:
                with open(self.source_path, 'r') as f:
                    self.data = json.load(f, 'windows-1251')
                self.ProcessModel()
                @public.mth
                def f2():
                    self.target_doc.ChangeState(self.target_doc.state_changed)
            except:
                log.exception()
                @public.mth
                def f3():
                    self.target_doc.ChangeState(self.target_doc.state_importfailed)

    def InitEnvironment(self):
        """Initilizes environment.

        Environment is generally the same as console local variables,
        so acces to them by module names and keywords like 'builder'.
        '"""

        environment = appdata.environment_manager.GetWorkEnvironment(self.target_doc, include_builder=True)

        self.builder        = environment.get('builder', None)
        self.part2          = environment.get('part2', None)
        self.p7tpl          = environment.get(self.p7tpl_doc.module_name, None)

        return self.builder and self.part2 and self.p7tpl

    def PrepareEnvironment(self):
        """Prepeares environment for import.
        
        Here opened all files needed by import.
        To check file is already opened here used FindDocumentByPaths document method.
        """

        if not bool(appconfig.get('paths.p7tpl_catalog') and appconfig.get('paths.rdl_catalog') and appconfig.get('catalog.proj_ns')):
            log('Import error: Catalog dependencies not set!\n')            
            return False

        self.target_doc.UpdateProps({'basens': appconfig.get('catalog.proj_ns')})

        self.p7tpl_doc = GraphDocument.FindDocumentByPaths([appconfig.get('paths.p7tpl_catalog')])
        if not self.p7tpl_doc:
            self.p7tpl_doc = GraphDocument()
            param = dict(name="Template set (Catalog)", chosen_part2=kb.ns_dm_part8, module_name="p7tpl")
            self.p7tpl_doc.OpenFiles([appconfig.get('paths.p7tpl_catalog')], **param)
            appdata.project.AddDocument(self.p7tpl_doc)

        self.pcardl_doc = GraphDocument.FindDocumentByPaths([appconfig.get('paths.rdl_catalog')])
        if not self.pcardl_doc:
            self.pcardl_doc = GraphDocument()
            param = dict(name='RDL (Catalog)', chosen_part2=kb.ns_dm_part2, namespaces=kb.namespaces_std, annotations=kb.annotations_pcardl_rdf)
            self.pcardl_doc.OpenFiles([appconfig.get('paths.rdl_catalog')], **param)
            appdata.project.AddDocument(self.pcardl_doc)

        ready = True

        """If file needed to be loaded, subscribe on it's events."""

        if not self.p7tpl_doc.CanView():
            wizard.Subscribe(self.p7tpl_doc, self)
            ready = False

        if not self.pcardl_doc.CanView():
            wizard.Subscribe(self.pcardl_doc, self)
            ready = False

        return ready

    def W_DocumentStateChanged(self, doc):
        """This handler detects that necessary files were loaded succesfully."""

        if doc.CanView(): 
            wizard.Unsubscribe(doc, self)
        elif doc.IsUnavailable():
            log('Import error: {0} unavailable!\n', doc.name)
            self.target_doc.ChangeState(self.target_doc.state_importfailed)
            wizard.Unsubscribe(doc, self)
        if self.p7tpl_doc.CanView() and self.pcardl_doc.CanView():
            self.enviponment_prepeared = True
            appdata.app.After(self.DoImport)

    def GetUnitByDesc(self, attribute):

        unit_type = attribute['unit']

        if unit_type == '':
            return None

        if unit_type in self.unit_generated:
            return self.unit_generated[unit_type]

        else:
            unit_item = self.part2.Scale()
            self.builder.annotate(id = unit_item, label=unit_type)
            self.unit_generated[unit_type] = unit_item
            return unit_item

    def GetAttributeById(self, attr_id):
        if attr_id in self.attr_generated:
            return self.attr_generated[attr_id]
        return None

    def GetAttributeByDesc(self, attribute):

        attr_id   = attribute['id']

        if attr_id == '':
            return None

        if attr_id in self.attr_generated:
            return self.attr_generated[attr_id]

        else:
            item    = None
            type    = attribute['type']

            if type == 'string':
                item = self.part2.ClassOfClassOfIndividual()
                self.builder.annotate(id = item, label=attr_id)

            elif type == 'real':
                item = self.part2.ClassOfIndirectProperty()
                self.builder.annotate(id = item, label=attr_id)

            elif type == 'integer':
                item = self.part2.EnumeratedPropertySet()
                self.builder.annotate(id = item, label=attr_id)

            elif type == 'date/time':
                item_a = self.part2.RoleAndDomain()
                self.builder.annotate(id = item_a, label="POSSESOR_OF_"+attr_id)
                self.attr_generated["POSSESOR_OF_"+attr_id] = item_a
                item_b = self.part2.RoleAndDomain()
                self.builder.annotate(id = item_b, label="RANGE_OF_"+attr_id)
                self.attr_generated["RANGE_OF_"+attr_id] = item_b
                self.p7tpl.Specialization(item_b, "http://posccaesar.org/rdl/RDS16432820")

                item = self.part2.ClassOfRelationshipWithSignature(hasClassOfEnd1 = item_a, hasClassOfEnd2 = item_b)

                self.builder.annotate(id = item, label=attr_id)

            elif type == 'reference':
                item = self.part2.ClassOfClassOfIndividual()
                self.builder.annotate(id = item, label=attr_id)

            else:
                return None

            self.part2.Classification(hasClassified=item, hasClassifier=self.attr_type)
            self.RusIdent(item, attribute['name'])

            self.attr_generated[attr_id] = item

            return item

    def ProcessAttribute(self, attribute, class_item):

        attr_item = self.GetAttributeByDesc(attribute)
        unit_item = self.GetUnitByDesc(attribute)

        if attr_item:
            type    = attribute['type']
            if type == 'string':
                self.p7tpl.ClassOfClassification(class_item, attr_item)
            elif type == 'real' and unit_item:
                self.p7tpl.PropertyRangeTypeRestrictionOfClass(class_item, attr_item, unit_item)
            elif type == 'integer':
                self.p7tpl.ClassOfClassification(class_item, attr_item)
            elif type == 'date/time':
                attr_id = "POSSESOR_OF_"+attribute['id']
                self.part2.Specialization(hasSubclass=class_item, hasSuperclass=self.GetAttributeById(attr_id))
            elif type == 'reference':
                self.p7tpl.ClassOfClassification(class_item, attr_item)
            else:
                pass
 
    def ReadClass(self, classnode, parent_attributes = [], parent_class = None):

        if classnode['id'] == '':
            return

        if self.attr_inheritance:
            attributes = parent_attributes[:]
        else:
            attributes = []

        class_item = self.part2.ClassOfIndividual()
        self.builder.annotate(id = class_item, label=classnode['id'])

        if parent_class:
            self.part2.Specialization(hasSubclass=class_item, hasSuperclass=parent_class)

        self.part2.Classification(hasClassified=class_item, hasClassifier=self.eq_class)
        self.RusIdent(class_item, classnode['name'])

        if 'attributes' in classnode:
            class_attributes = classnode['attributes']
            if type(class_attributes)==type(list()):
                attributes[len(attributes):] = class_attributes
            elif type(class_attributes)==type(dict()):
                attributes[len(attributes):] = [class_attributes]
            else:
                log("err!!")

        for subitem in attributes:
            self.ProcessAttribute(subitem, class_item)

        if 'subClasses' in classnode:
            class_subclasses = classnode['subClasses']
            if type(class_subclasses)==type(list()):
                for subitem in class_subclasses:
                    self.ReadClass(subitem, attributes, class_item)
            elif type(class_subclasses)==type(dict()):
                self.ReadClass(class_subclasses, attributes, class_item)
            else:
                log("err!!")

    def ProcessModel(self):

        self.ru_ident = self.part2.ClassOfClassOfIdentification()
        self.builder.annotate(id = self.ru_ident, label='CATALOG RUSSIAN IDENTIFICATION')

        self.attr_type = self.part2.ClassOfClass()
        self.builder.annotate(id = self.attr_type, label='CATALOG ATTRIBUTE TYPE')

        self.eq_class = self.part2.ClassOfClassOfIndividual()
        self.builder.annotate(id = self.eq_class, label='CATALOG EQUIPMENT CLASS')

        data = self.data
        self.attr_generated = {}
        self.unit_generated = {}
        self.ReadClass(data)

    def RusIdent(self, item, name):
        exs = self.part2.ExpressString()
        self.builder.annotate(id = exs, label=name)
        coi = self.part2.ClassOfIdentification(hasRepresented=item, hasPattern=exs)
        self.p7tpl.Classification(coi, self.ru_ident)
Beispiel #2
0
class TabLanImporter:
    def __init__(self, target_doc, import_source):

        self.source_path = import_source[0]
        self.target_doc = target_doc
        self.enviponment_prepeared = self.PrepareEnvironment()

        self.part2names = {}
        for (k, v) in kb.part2_itself.iteritems():
            self.part2names[v['name']] = v['name']

        self.cardinalities = cardinalities_cnt()
        self.relations = {}
        for k in dir(self):
            if k.startswith('R_'):
                self.relations[k[2:].replace('_', ' ')] = getattr(self, k)

        self.DoImport()

    def DoImport(self):

        if not self.enviponment_prepeared:
            return

        if not self.InitEnvironment():
            self.target_doc.ChangeState(self.target_doc.state_importfailed)
            return

        @public.wth(tm.ext.importing_doc.format(self.target_doc.name),
                    self.target_doc, self.p7tpl_doc, self.pcardl_doc)
        def f():
            try:
                self.rd = excel_reader.ExcelReader(self.source_path)
                self.ProcessModel()

                @public.mth
                def f2():
                    self.target_doc.ChangeState(self.target_doc.state_changed)
            except:
                log.exception()

                @public.mth
                def f3():
                    self.target_doc.ChangeState(
                        self.target_doc.state_importfailed)

    def InitEnvironment(self):
        environment = appdata.environment_manager.GetWorkEnvironment(
            self.target_doc, include_builder=True)
        self.builder = environment.get('builder', None)
        self.part2 = environment.get('part2', None)
        self.p7tpl = environment.get(self.p7tpl_doc.module_name, None)
        return self.builder and self.part2 and self.p7tpl

    def PrepareEnvironment(self):

        if not bool(
                appconfig.get('paths.p7tpl_tablan')
                and appconfig.get('paths.rdl_tablan')
                and appconfig.get('tablan.proj_ns')):
            log('Import error: TabLan dependencies not set!\n')
            return False

        self.target_doc.UpdateProps(
            {'basens': appconfig.get('tablan.proj_ns')})

        self.p7tpl_doc = GraphDocument.FindDocumentByPaths(
            [appconfig.get('paths.p7tpl_tablan')])
        if not self.p7tpl_doc:
            self.p7tpl_doc = GraphDocument()
            param = dict(name="Template set (TabLan)",
                         chosen_part2=kb.ns_dm_part8,
                         module_name="p7tpl")
            self.p7tpl_doc.OpenFiles([appconfig.get('paths.p7tpl_tablan')],
                                     **param)
            appdata.project.AddDocument(self.p7tpl_doc)

        self.pcardl_doc = GraphDocument.FindDocumentByPaths(
            [appconfig.get('paths.rdl_tablan')])
        if not self.pcardl_doc:
            self.pcardl_doc = GraphDocument()
            param = dict(name='RDL (TabLan)',
                         chosen_part2=kb.ns_dm_part2,
                         namespaces=kb.namespaces_std,
                         annotations=kb.annotations_pcardl_rdf)
            self.pcardl_doc.OpenFiles([appconfig.get('paths.rdl_tablan')],
                                      **param)
            appdata.project.AddDocument(self.pcardl_doc)

        ready = True

        if not self.p7tpl_doc.CanView():
            wizard.Subscribe(self.p7tpl_doc, self)
            ready = False

        if not self.pcardl_doc.CanView():
            wizard.Subscribe(self.pcardl_doc, self)
            ready = False

        return ready

    def W_DocumentStateChanged(self, doc):
        if doc.CanView():
            wizard.Unsubscribe(doc, self)
        elif doc.IsUnavailable():
            log('Import error: {0} unavailable!\n', doc.name)
            self.target_doc.ChangeState(self.target_doc.state_importfailed)
            wizard.Unsubscribe(doc, self)
        if self.p7tpl_doc.CanView() and self.pcardl_doc.CanView():
            self.enviponment_prepeared = True
            appdata.app.After(self.DoImport)

    def ProcessModel(self):

        rd = self.rd

        ids = {}
        ru_names = {}
        en_names = {}
        doc_names = {}

        def is_section(r):
            return r.text('Section') != ''

        # classes creation

        @rd.SafeRows('Class Definitions')
        def f(r):
            if is_section(r): return

            class_id = r.text('URI')
            ru_name = r.text('Russian Unique Class Name')
            en_name = r.text('English Unique Class Name')

            if not en_name and not ru_name:
                r.row_error(
                    'Russian or english name is required for every class')

            if class_id.startswith('rdl:'):
                class_id = 'http://posccaesar.org/rdl/' + class_id[4:]
            elif class_id.startswith('til:'):
                class_id = 'http://techinvestlab.ru/data#' + class_id[4:]
            else:
                p2type = r.known('Part 2 Type', self.part2names)
                class_id = getattr(self.part2, p2type)()
                if en_name:
                    self.builder.annotate(id=class_id,
                                          label=en_name,
                                          label_en=en_name)
                if ru_name:
                    if not en_name:
                        self.builder.annotate(id=class_id,
                                              label=ru_name,
                                              label_ru=ru_name)
                    else:
                        self.builder.annotate(id=class_id, label_ru=ru_name)
                source = r.nonempty('Source')
                self.builder.annotate(id=class_id, annSource=source)
            #else:
            #    r.row_error('Wrong URI field')

            if en_name:
                en_names[class_id] = en_name
                ids[en_name] = class_id
            if ru_name:
                ru_names[class_id] = ru_name
                ids[ru_name] = class_id

        # for later use
        self.EmptyClass = ids['EmptyClass']

        # structure model creation

        @rd.SafeRows('Structure Model')
        def f(r):
            if is_section(r): return

            item_name = r.text('Item ID')
            if not item_name:
                return

            item = self.part2.ClassOfInformationObject()
            doc_names[item] = item_name
            ids[item_name] = item
            self.builder.annotate(id=item, label=item_name)

        self.was_item = None

        # structure model specification

        @rd.SafeRows('Structure Model')
        def f(r):
            if is_section(r): return

            item = r.known_or_empty('Item ID', ids)

            if not item:
                item = self.was_item

                classifier = r.known_or_empty('Classifier Class', ids)
                if classifier:
                    self.part2.Classification(hasClassified=item,
                                              hasClassifier=classifier)

                subject = r.known_or_empty('Item Subject', ids)
                if subject:
                    self.p7tpl.DescriptionByInformationObject(subject, item)
                return
            else:
                self.was_item = item

            item_class = r.known('Item Class', ids)
            text = r.nonempty('Item Text')
            whole = r.known_or_empty('Item of Whole', ids)
            classifier = r.known_or_empty('Classifier Class', ids)
            subject = r.known_or_empty('Item Subject', ids)

            if text:
                self.builder.annotate(id=item, annTextDefinition=text)

            self.part2.Specialization(hasSubclass=item,
                                      hasSuperclass=item_class)
            if classifier:
                self.part2.Classification(hasClassified=item,
                                          hasClassifier=classifier)
            if whole:
                self.p7tpl.ClassOfArrangementOfIndividual(item, whole)
            if subject:
                self.p7tpl.DescriptionByInformationObject(subject, item)

        # classes specification

        @rd.SafeRows('Class Definitions')
        def f(r):
            if is_section(r): return

            ru_name = r.text('Russian Unique Class Name')
            en_name = r.text('English Unique Class Name')
            if ru_name:
                class_id = ids[ru_name]
            else:
                class_id = ids[en_name]

            superclass = r.known_or_empty('Superclass', ids)
            classifier = r.known_or_empty('Classifier Class', ids)

            if superclass:
                self.part2.Specialization(hasSubclass=class_id,
                                          hasSuperclass=superclass)
            if classifier:
                self.part2.Classification(hasClassified=class_id,
                                          hasClassifier=classifier)

        # properties

        @rd.SafeRows('Class Properties')
        def f(r):
            if is_section(r): return

            # now
            class_id = r.known('Class Name', ids)
            prop = r.known('Property Name', ids)
            ind_prop = r.known_or_empty('Indirect Property Name', ids)
            vmin = r.nonempty('Property Min')
            vmax = r.nonempty('Property Max')
            source = r.nonempty('Source')

            pr_min = ids.get(vmin)
            if pr_min is None:
                pr_min = self.part2.Property(label=vmin)
                ids[vmin] = pr_min

            pr_max = ids.get(vmax)
            if pr_max is None:
                pr_max = self.part2.Property(label=vmax)
                ids[vmax] = pr_max

            rng = self.part2.PropertyRange(annSource=source)
            self.part2.Specialization(hasSubclass=rng,
                                      hasSuperclass=prop,
                                      annSource=source)
            self.p7tpl.LowerUpperOfPropertyRange(rng,
                                                 pr_min,
                                                 pr_max,
                                                 annSource=source)

            if ind_prop:
                self.p7tpl.PropertyRangeRestrictionOfClass(class_id,
                                                           ind_prop,
                                                           rng,
                                                           annSource=source)
            else:
                self.part2.ClassOfClassification(hasClassOfClassified=class_id,
                                                 hasClassOfClassifier=rng,
                                                 annSource=source)

        # classifiers

        @rd.SafeRows('Classifier Definition')
        def f(r):
            if is_section(r): return

            class_id = r.known('Class Name', ids)
            superclass = r.known_or_empty('Superclass Name', ids)
            rel_class = r.known_or_empty('Classifier Relationship Class', ids)
            class_class = r.known_or_empty('Class of Classifier Classes', ids)
            source = r.nonempty('Source')

            if superclass:
                rel_id = self.part2.Specialization(hasSubclass=class_id,
                                                   hasSuperclass=superclass,
                                                   annSource=source)
                if rel_class:
                    self.part2.Classification(hasClassified=rel_id,
                                              hasClassifier=rel_class,
                                              annSource=source)
            if class_class:
                self.part2.Classification(hasClassified=class_id,
                                          hasClassifier=class_class,
                                          annSource=source)

        # breakdown

        @rd.SafeRows('Breakdown Definition')
        def f(r):
            if is_section(r): return

            class_id = r.known('Class Name', ids)
            whole_class = r.known_or_empty('Whole Class Name', ids)
            rel_class = r.known_or_empty('Breakdown Relationship Class', ids)
            class_class = r.known_or_empty('Class of Breakdown Classes', ids)
            source = r.nonempty('Source')

            if whole_class:
                rel_id = self.part2.ClassOfCompositionOfIndividual(
                    hasClassOfPart=class_id,
                    hasClassOfWhole=whole_class,
                    annSource=source)
                if rel_class:
                    self.part2.Classification(hasClassified=rel_id,
                                              hasClassifier=rel_class,
                                              annSource=source)
            if class_class:
                self.part2.Classification(hasClassified=class_id,
                                          hasClassifier=class_class,
                                          annSource=source)

        # relationships

        @rd.SafeRows('Other Relationships')
        def f(r):
            if is_section(r): return

            role1 = r.known('Role 1', ids)
            role1c = r.known_or_empty('Role 1 Cardinality', self.cardinalities)
            rel_code = r.known('Relates to', self.relations)
            role2 = r.known('Role 2', ids)
            role2c = r.known_or_empty('Role 2 Cardinality', self.cardinalities)
            source = r.nonempty('Source')

            rel_id = rel_code(role1, role2, role1c, role2c, source)

        # requirements

        @rd.SafeRows('Requirements')
        def f(r):
            if is_section(r): return

            status = r.known('Statement Classification', ids)
            role1 = r.known('Role 1', ids)
            role1c = r.known_or_empty('Role 1 Cardinality', self.cardinalities)
            rel_code = r.known('Relates to', self.relations)
            role2 = r.known('Role 2', ids)
            role2c = r.known_or_empty('Role 2 Cardinality', self.cardinalities)
            source = r.nonempty('Source')

            rel_id = rel_code(role1, role2, role1c, role2c, source)

            if rel_id:
                if type(rel_id) == tuple:
                    rel_id = rel_id[0]
                    self.part2.Specialization(hasSubclass=rel_id,
                                              hasSuperclass=status,
                                              annSource=source)
                else:
                    self.part2.Classification(hasClassified=rel_id,
                                              hasClassifier=status,
                                              annSource=source)

    def R_is_described_by(self, role1, role2, role1c, role2c, source):
        pi = self.part2.PossibleIndividual(annSource=source)
        self.part2.Classification(hasClassified=pi,
                                  hasClassifier=role2,
                                  annSource=source)
        rel_id = self.part2.Description(hasRepresented=role1,
                                        hasSign=pi,
                                        annSource=source)
        return rel_id

    def R_participates_in(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.ClassOfCompositionOfIndividual(
            hasClassOfPart=role1, hasClassOfWhole=role2, annSource=source)
        if role1c is not None:
            if role1c[1] == "*":
                self.p7tpl.CardinalityEnd1Min(rel_id,
                                              role1c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd1MinMax(rel_id,
                                                 role1c[0],
                                                 role1c[1],
                                                 annSource=source)
        if role2c is not None:
            if role2c[1] == "*":
                self.p7tpl.CardinalityEnd2Min(rel_id,
                                              role2c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd2MinMax(rel_id,
                                                 role2c[0],
                                                 role2c[1],
                                                 annSource=source)
        return rel_id, 1

    def R_is_a_predecessor_in_time_of(self, role1, role2, role1c, role2c,
                                      source):
        rel_id = self.part2.ClassOfTemporalSequence(
            hasClassOfPredecessor=role1,
            hasClassOfSuccessor=role2,
            annSource=source)
        if role1c is not None:
            if role1c[1] == "*":
                self.p7tpl.CardinalityEnd1Min(rel_id,
                                              role1c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd1MinMax(rel_id,
                                                 role1c[0],
                                                 role1c[1],
                                                 annSource=source)
        if role2c is not None:
            if role2c[1] == "*":
                self.p7tpl.CardinalityEnd2Min(rel_id,
                                              role2c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd2MinMax(rel_id,
                                                 role2c[0],
                                                 role2c[1],
                                                 annSource=source)
        return rel_id, 1

    def R_has_as_part(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.ClassOfCompositionOfIndividual(
            hasClassOfPart=role2, hasClassOfWhole=role1, annSource=source)
        if role1c is not None:
            if role1c[1] == "*":
                self.p7tpl.CardinalityEnd1Min(rel_id,
                                              role1c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd1MinMax(rel_id,
                                                 role1c[0],
                                                 role1c[1],
                                                 annSource=source)
        if role2c is not None:
            if role2c[1] == "*":
                self.p7tpl.CardinalityEnd2Min(rel_id,
                                              role2c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd2MinMax(rel_id,
                                                 role2c[0],
                                                 role2c[1],
                                                 annSource=source)
        return rel_id, 1

    def R_is_disjoint(self, role1, role2, role1c, role2c, source):
        # self.p7tpl.IntersectionOf2Classes not present in Part 8 files
        eset = self.part2.EnumeratedSetOfClass(annSource=source)
        self.part2.Classification(hasClassified=role1,
                                  hasClassifier=eset,
                                  annSource=source)
        self.part2.Classification(hasClassified=role2,
                                  hasClassifier=eset,
                                  annSource=source)
        self.p7tpl.IntersectionOfSetOfClass(eset,
                                            self.EmptyClass,
                                            annSource=source)

    def R_is_performed_by(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.ClassOfCompositionOfIndividual(
            hasClassOfPart=role2, hasClassOfWhole=role1, annSource=source)
        if role1c is not None:
            if role1c[1] == "*":
                self.p7tpl.CardinalityEnd1Min(rel_id,
                                              role1c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd1MinMax(rel_id,
                                                 role1c[0],
                                                 role1c[1],
                                                 annSource=source)
        if role2c is not None:
            if role2c[1] == "*":
                self.p7tpl.CardinalityEnd2Min(rel_id,
                                              role2c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd2MinMax(rel_id,
                                                 role2c[0],
                                                 role2c[1],
                                                 annSource=source)
        return rel_id, 1

    def R_is_related_to(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.OtherRelationship(hasEnd1=role1,
                                              hasEnd2=role2,
                                              annSource=source)
        if role1c is not None:
            if role1c[1] == "*":
                self.p7tpl.CardinalityEnd1Min(rel_id,
                                              role1c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd1MinMax(rel_id,
                                                 role1c[0],
                                                 role1c[1],
                                                 annSource=source)
        if role2c is not None:
            if role2c[1] == "*":
                self.p7tpl.CardinalityEnd2Min(rel_id,
                                              role2c[0],
                                              annSource=source)
            else:
                self.p7tpl.CardinalityEnd2MinMax(rel_id,
                                                 role2c[0],
                                                 role2c[1],
                                                 annSource=source)
        return rel_id

    def R_is_classified_as(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.Classification(hasClassified=role1,
                                           hasClassifier=role2,
                                           annSource=source)
        return rel_id

    def R_is_subclass_of(self, role1, role2, role1c, role2c, source):
        rel_id = self.part2.Specialization(hasSubclass=role1,
                                           hasSuperclass=role2,
                                           annSource=source)
        return rel_id

    def R_complies_to_description_in(self, role1, role2, role1c, role2c,
                                     source):
        pi = self.part2.PossibleIndividual(annSource=source)
        self.part2.Classification(hasClassified=pi,
                                  hasClassifier=role2,
                                  annSource=source)
        rel_id = self.part2.Description(hasRepresented=role1,
                                        hasSign=pi,
                                        annSource=source)
        return rel_id