Example #1
0
class PropertyClass:
    _context: Context
    _id: str
    _name: str
    _ontology_id: str
    _superproperties: List[str]
    _object: str
    _subject: str
    _gui_element: str
    _gui_attributes: Dict[str, str]
    _label: LangString
    _comment: LangString
    _editable: bool
    _linkvalue: bool
    _changed: Set[str]

    def __init__(self,
                 con: Connection,
                 context: Context,
                 id: Optional[str] = None,
                 name: Optional[str] = None,
                 ontology_id: Optional[str] = None,
                 superproperties: Optional[List[Union['PropertyClass',
                                                      str]]] = None,
                 object: Optional[str] = None,
                 subject: Optional[str] = None,
                 gui_element: Optional[str] = None,
                 gui_attributes: Optional[Dict[str, str]] = None,
                 label: Optional[Union[LangString, str]] = None,
                 comment: Optional[Union[LangString, str]] = None,
                 editable: Optional[bool] = None,
                 linkvalue: Optional[bool] = None):
        if not isinstance(con, Connection):
            raise BaseError(
                '"con"-parameter must be an instance of Connection')
        if not isinstance(context, Context):
            raise BaseError(
                '"context"-parameter must be an instance of Context')
        self.con = con
        self._context = context
        self._id = id
        self._name = name
        self._ontology_id = ontology_id
        if isinstance(superproperties, PropertyClass):
            self._superproperties = list(map(lambda a: a.id, superproperties))
        else:
            self._superproperties = superproperties
        self._object = object
        self._subject = subject
        self._gui_element = gui_element
        self._gui_attributes = gui_attributes
        #
        # process label
        #
        if label is not None:
            if isinstance(label, str):
                self._label = LangString(label)
            elif isinstance(label, LangString):
                self._label = label
            else:
                raise BaseError('Invalid LangString for label!')
        else:
            self._label = None
        #
        # process comment
        #
        if comment is not None:
            if isinstance(comment, str):
                self._comment = LangString(comment)
            elif isinstance(comment, LangString):
                self._comment = comment
            else:
                raise BaseError('Invalid LangString for comment!')
        else:
            self._comment = None

        self._editable = editable
        self._linkvalue = linkvalue
        self._changed = set()

    #
    # Here follows a list of getters/setters
    #
    @property
    def name(self) -> Optional[str]:
        return self._name

    @name.setter
    def name(self, value: str) -> None:
        raise BaseError('"name" cannot be modified!')

    @property
    def id(self) -> Optional[str]:
        return self._id

    @id.setter
    def id(self, value: str) -> None:
        raise BaseError('"id" cannot be modified!')

    @property
    def ontology_id(self) -> Optional[str]:
        return self._ontology_id

    @ontology_id.setter
    def ontology_id(self, value: str) -> None:
        raise BaseError('"ontology_id" cannot be modified!')

    @property
    def superproperties(self) -> Optional[str]:
        return self._superproperties

    @superproperties.setter
    def superproperties(self, value: str) -> None:
        raise BaseError('"superproperties" cannot be modified!')

    @property
    def object(self) -> Optional[str]:
        return self._object

    @object.setter
    def object(self, value: Any):
        raise BaseError('"object" cannot be modified!')

    @property
    def subject(self) -> Optional[str]:
        return self._subject

    @subject.setter
    def subject(self, value: Any):
        raise BaseError('"subject" cannot be modified!')

    @property
    def gui_element(self) -> Optional[str]:
        return self._gui_element

    @gui_element.setter
    def gui_element(self, value: str) -> None:
        self._gui_element = value
        self._changed.append('gui_element')

    @property
    def gui_attributes(self) -> Optional[Dict[str, str]]:
        return self._gui_attributes

    @gui_attributes.setter
    def gui_attributes(self, value: List[Dict[str, str]]) -> None:
        self._gui_attributes = value
        self._changed.append('gui_attributes')

    def addGuiAttribute(self, key: str, value: str) -> None:
        self._gui_attributes[key] = value
        self._changed.append('gui_attributes')

    def rmGuiAttribute(self, key: str) -> None:
        if self._gui_attributes.get(key) is not None:
            del self._gui_attributes[key]
            self._changed.append('gui_attributes')

    @property
    def label(self) -> Optional[LangString]:
        return self._label

    @label.setter
    def label(self, value: Optional[Union[LangString, str]]) -> None:
        if value is None:
            self._label.empty()  # clear all labels
        else:
            if isinstance(value, LangString):
                self._label = value
            elif isinstance(value, str):
                self._label = LangString(value)
            else:
                raise BaseError('Not a valid LangString')
        self._changed.add('label')

    def addLabel(self, lang: Union[Languages, str], value: str) -> None:
        self._label[lang] = value
        self._changed.add('label')

    def rmLabel(self, lang: Union[Languages, str]) -> None:
        del self._label[lang]
        self._changed.add('label')

    @property
    def comment(self) -> Optional[LangString]:
        return self._comment

    @comment.setter
    def comment(self, value: Optional[LangString]) -> None:
        if value is None:
            self._comment.empty()  # clear all comments!
        else:
            if isinstance(value, LangString):
                self._comment = value
            elif isinstance(value, str):
                self._comment = LangString(value)
            else:
                raise BaseError('Not a valid LangString')
        self._changed.add('comment')

    def addComment(self, lang: Union[Languages, str], value: str) -> None:
        self._comment[lang] = value
        self._changed.add('comment')

    def rmComment(self, lang: Union[Languages, str]) -> None:
        del self._comment[lang]
        self._changed.add('comment')

    @property
    def editable(self) -> bool:
        return self._editable

    @editable.setter
    def editable(self, value: bool) -> None:
        raise BaseError('"editable" cannot be modified!')

    @property
    def linkvalue(self) -> bool:
        return self._linkvalue

    @linkvalue.setter
    def linkvalue(self) -> None:
        raise BaseError('"linkvalue" cannot be modified!')

    @classmethod
    def fromJsonObj(cls, con: Connection, context: Context,
                    json_obj: Any) -> Any:
        if isinstance(json_obj, list):
            json_obj = json_obj[
                0]  # TODO: Is it possible to have more than one element in the list??
        if not isinstance(con, Connection):
            raise BaseError(
                '"con"-parameter must be an instance of Connection')
        if not isinstance(context, Context):
            raise BaseError(
                '"context"-parameter must be an instance of Context')
        rdf = context.prefixFromIri(
            "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
        rdfs = context.prefixFromIri("http://www.w3.org/2000/01/rdf-schema#")
        owl = context.prefixFromIri("http://www.w3.org/2002/07/owl#")
        xsd = context.prefixFromIri("http://www.w3.org/2001/XMLSchema#")
        knora_api = context.prefixFromIri(
            "http://api.knora.org/ontology/knora-api/v2#")
        salsah_gui = context.prefixFromIri(
            "http://api.knora.org/ontology/salsah-gui/v2#")

        if not (json_obj.get(knora_api + ':isResourceProperty')):
            raise BaseError("This is not a property!")
        if json_obj.get('@id') is None:
            raise BaseError('Property class has no "@id"!')
        tmp_id = json_obj.get('@id').split(':')
        id = context.iriFromPrefix(tmp_id[0]) + '#' + tmp_id[1]
        ontology_id = tmp_id[0]
        name = tmp_id[1]
        superproperties_obj = json_obj.get(rdfs + ':subPropertyOf')
        superproperties: List[Union[None, str]]
        if not isinstance(superproperties_obj, list):
            superproperties_obj = [superproperties_obj
                                   ]  # make a list out of it
        if superproperties_obj is not None:
            superprops: List[Any] = list(
                filter(lambda a: a.get('@id') is not None,
                       superproperties_obj))
            superproperties = list(map(lambda a: a['@id'], superprops))
        else:
            superproperties = None
        object = WithId(json_obj.get(knora_api + ':objectType')).str()
        subject = WithId(json_obj.get(knora_api + ':subjectType')).str()
        label = LangString.fromJsonLdObj(json_obj.get(rdfs + ':label'))
        comment = LangString.fromJsonLdObj(json_obj.get(rdfs + ':comment'))
        gui_element = None
        if json_obj.get(salsah_gui + ':guiElement') is not None:
            gui_element = WithId(json_obj.get(salsah_gui +
                                              ':guiElement')).str()
        gui_attributes_list = json_obj.get(salsah_gui + ':guiAttribute')
        gui_attributes: Union[None, Dict[str, str]] = None
        if gui_attributes_list is not None:
            gui_attributes = {}
            if not isinstance(gui_attributes_list, list):
                gui_attributes_list = [gui_attributes_list]
            for ga in gui_attributes_list:
                tmp = ga.split('=')
                if len(tmp) == 1:
                    gui_attributes[tmp[0]] = ''
                else:
                    gui_attributes[tmp[0]] = tmp[1]

        editable = json_obj.get(knora_api + ':isEditable')
        linkvalue = json_obj.get(knora_api + ':isLinkProperty')
        return cls(con=con,
                   context=context,
                   id=id,
                   name=name,
                   ontology_id=ontology_id,
                   superproperties=superproperties,
                   object=object,
                   subject=subject,
                   gui_element=gui_element,
                   gui_attributes=gui_attributes,
                   label=label,
                   comment=comment,
                   editable=editable,
                   linkvalue=linkvalue)

    def toJsonObj(self,
                  lastModificationDate: LastModificationDate,
                  action: Actions,
                  what: Optional[str] = None) -> Any:
        def resolve_propref(resref: str):
            tmp = resref.split(':')
            if len(tmp) > 1:
                if tmp[0]:
                    return {
                        "@id": resref
                    }  # fully qualified name in the form "prefix:name"
                else:
                    return {
                        "@id":
                        self._context.prefixFromIri(self._ontology_id) + ':' +
                        tmp[1]
                    }  # ":name" in current ontology
            else:
                return {
                    "@id": "knora-api:" + resref
                }  # no ":", must be from knora-api!

        tmp = {}
        exp = re.compile('^http.*')  # It is already a fully IRI
        if exp.match(self._ontology_id):
            propid = self._context.prefixFromIri(
                self._ontology_id) + ":" + self._name
            ontid = self._ontology_id
        else:
            propid = self._ontology_id + ":" + self._name
            ontid = self._context.iriFromPrefix(self._ontology_id)
        if action == Actions.Create:
            if self._name is None:
                raise BaseError("There must be a valid property class name!")
            if self._ontology_id is None:
                raise BaseError("There must be a valid ontology_id given!")
            if self._superproperties is None:
                superproperties = [{"@id": "knora-api:hasValue"}]
            else:
                superproperties = list(
                    map(resolve_propref, self._superproperties))

            tmp = {
                "@id":
                ontid,  # self._ontology_id,
                "@type":
                "owl:Ontology",
                "knora-api:lastModificationDate":
                lastModificationDate.toJsonObj(),
                "@graph": [{
                    "@id": propid,
                    "@type": "owl:ObjectProperty",
                    "rdfs:label": self._label.toJsonLdObj(),
                    "rdfs:subPropertyOf": superproperties
                }],
                "@context":
                self._context.toJsonObj()
            }
            if self._comment is not None:
                if not self._comment.isEmpty():
                    tmp['@graph'][0][
                        "rdfs:comment"] = self._comment.toJsonLdObj()
            if self._subject is not None:
                tmp['@graph'][0]["knora-api:subjectType"] = resolve_propref(
                    self._subject)
            if self._object is not None:
                tmp['@graph'][0]["knora-api:objectType"] = resolve_propref(
                    self._object)
            if self._gui_element is not None:
                tmp['@graph'][0]["salsah-gui:guiElement"] = {
                    "@id": self._gui_element
                }
            if self._gui_attributes:
                ga = list(
                    map(lambda x: x[0] + '=' + str(x[1]),
                        self._gui_attributes.items()))
                tmp['@graph'][0]["salsah-gui:guiAttribute"] = ga
        elif action == Actions.Update:
            tmp = {
                "@id": ontid,  # self._ontology_id,
                "@type": "owl:Ontology",
                "knora-api:lastModificationDate":
                lastModificationDate.toJsonObj(),
                "@graph": [{
                    "@id": propid,
                    "@type": "owl:ObjectProperty",
                }],
                "@context": self._context.toJsonObj(),
            }
            if what == 'label':
                if not self._label.isEmpty() and 'label' in self._changed:
                    tmp['@graph'][0]['rdfs:label'] = self._label.toJsonLdObj()
            if what == 'comment':
                if not self._comment.isEmpty() and 'comment' in self._changed:
                    tmp['@graph'][0][
                        'rdfs:comment'] = self._comment.toJsonLdObj()

        return tmp

    def create(
        self, last_modification_date: LastModificationDate
    ) -> Tuple[LastModificationDate, 'PropertyClass']:
        jsonobj = self.toJsonObj(last_modification_date, Actions.Create)
        jsondata = json.dumps(jsonobj, cls=SetEncoder, indent=2)
        result = self.con.post('/v2/ontologies/properties', jsondata)
        last_modification_date = LastModificationDate(
            result['knora-api:lastModificationDate'])
        return last_modification_date, PropertyClass.fromJsonObj(
            self.con, self._context, result['@graph'])

    def update(
        self, last_modification_date: LastModificationDate
    ) -> Tuple[LastModificationDate, 'ResourceClass']:
        #
        # Note: Knora is able to change only one thing per call, either label or comment!
        #
        result = None
        something_changed = False
        if 'label' in self._changed:
            jsonobj = self.toJsonObj(last_modification_date, Actions.Update,
                                     'label')
            jsondata = json.dumps(jsonobj, cls=SetEncoder, indent=4)
            result = self.con.put('/v2/ontologies/properties', jsondata)
            last_modification_date = LastModificationDate(
                result['knora-api:lastModificationDate'])
            something_changed = True
        if 'comment' in self._changed:
            jsonobj = self.toJsonObj(last_modification_date, Actions.Update,
                                     'comment')
            jsondata = json.dumps(jsonobj, cls=SetEncoder, indent=4)
            result = self.con.put('/v2/ontologies/properties', jsondata)
            last_modification_date = LastModificationDate(
                result['knora-api:lastModificationDate'])
            something_changed = True
        if something_changed:
            return last_modification_date, PropertyClass.fromJsonObj(
                self.con, self._context, result['@graph'])
        else:
            return last_modification_date, self

    def delete(
            self, last_modification_date: LastModificationDate
    ) -> LastModificationDate:
        result = self.con.delete('/v2/ontologies/properties/' +
                                 quote_plus(self._id) +
                                 '?lastModificationDate=' +
                                 str(last_modification_date))
        return LastModificationDate(result['knora-api:lastModificationDate'])

    def print(self, offset: int = 0):
        blank = ' '
        print(f'{blank:>{offset}}Property Class Info')
        print(f'{blank:>{offset+2}}Name:            {self._name}')
        print(f'{blank:>{offset+2}}Ontology prefix: {self._ontology_id}')
        print(f'{blank:>{offset+2}}Superproperties:')
        if self._superproperties is not None:
            for sc in self._superproperties:
                print(f'{blank:>{offset + 4}}{sc}')
        if self._label is not None:
            print(f'{blank:>{offset + 2}}Labels:')
            self._label.print(offset + 4)
        if self._subject is not None:
            print(f'{blank:>{offset + 4}}Subject: {self._subject}')
        if self._object is not None:
            print(f'{blank:>{offset + 4}}Object: {self._object}')
        if self._gui_element is not None:
            print(f'{blank:>{offset + 4}}Guielement: {self._gui_element}')
        if self._gui_attributes is not None:
            print(f'{blank:>{offset + 4}}Gui Attributes:')
            if self._gui_attributes is not None:
                pprint(self._gui_attributes)
                for (attname, attvalue) in self._gui_attributes.items():
                    print(
                        f'{blank:>{offset + 6}}Attribute: {attname} Value: {attvalue}'
                    )
        if self._comment is not None:
            print(f'{blank:>{offset + 2}}Comments:')
            self._comment.print(offset + 4)
        if self._editable is not None:
            print(f'{blank:>{offset + 4}}Editable: {self._editable}')
        if self._linkvalue is not None:
            print(f'{blank:>{offset + 4}}Editable: {self._linkvalue}')
Example #2
0
class ResourceClass:
    con: Connection
    _context: Context
    _id: str
    _name: str
    _ontology_id: str
    _superclasses: List[str]
    _label: LangString
    _comment: LangString
    _permissions: str
    _has_properties: Dict[str, HasProperty]
    _changed: Set[str]

    def __init__(self,
                 con: Connection,
                 context: Context,
                 id: Optional[str] = None,
                 name: Optional[str] = None,
                 ontology_id: Optional[str] = None,
                 superclasses: Optional[List[Union['ResourceClass',
                                                   str]]] = None,
                 label: Optional[Union[LangString, str]] = None,
                 comment: Optional[Union[LangString, str]] = None,
                 permissions: Optional[str] = None,
                 has_properties: Optional[Dict[str, HasProperty]] = None):
        if not isinstance(con, Connection):
            raise BaseError(
                '"con"-parameter must be an instance of Connection')
        if not isinstance(context, Context):
            raise BaseError(
                '"context"-parameter must be an instance of Context')
        self.con = con
        self._context = context
        self._id = id
        self._name = name
        self._ontology_id = ontology_id
        if isinstance(superclasses, ResourceClass):
            self._superclasses = list(map(lambda a: a.id, superclasses))
        else:
            self._superclasses = superclasses
        #
        # process label
        #
        if label is not None:
            if isinstance(label, str):
                self._label = LangString(label)
            elif isinstance(label, LangString):
                self._label = label
            else:
                raise BaseError('Invalid LangString for label!')
        else:
            self._label = None
        #
        # process comment
        #
        if comment is not None:
            if isinstance(comment, str):
                self._comment = LangString(comment)
            elif isinstance(comment, LangString):
                self._comment = comment
            else:
                raise BaseError('Invalid LangString for comment!')
        else:
            self._comment = None
        self._permissions = permissions
        self._has_properties = has_properties
        self._changed = set()

    #
    # Here follows a list of getters/setters
    #
    @property
    def name(self) -> Optional[str]:
        return self._name

    @name.setter
    def name(self, value: str) -> None:
        raise BaseError('"name" cannot be modified!')

    @property
    def id(self) -> Optional[str]:
        return self._id

    @id.setter
    def id(self, value: str) -> None:
        raise BaseError('"id" cannot be modified!')

    @property
    def ontology_id(self) -> Optional[str]:
        return self._ontology_id

    @ontology_id.setter
    def ontology_id(self, value: str) -> None:
        raise BaseError('"ontology_id" cannot be modified!')

    @property
    def superclasses(self) -> Optional[List[str]]:
        return self._superclasses

    @superclasses.setter
    def superclasses(self, value: List[str]) -> None:
        raise BaseError('"superclasses" cannot be modified!')

    @property
    def label(self) -> Optional[LangString]:
        return self._label

    @label.setter
    def label(self, value: Optional[Union[LangString, str]]) -> None:
        if value is None:
            self._label.empty()  # clear all labels
        else:
            if isinstance(value, LangString):
                self._label = value
            elif isinstance(value, str):
                self._label = LangString(value)
            else:
                raise BaseError('Not a valid LangString')
        self._changed.add('label')

    def addLabel(self, lang: Union[Languages, str], value: str) -> None:
        self._label[lang] = value
        self._changed.add('label')

    def rmLabel(self, lang: Union[Languages, str]) -> None:
        del self._label[lang]
        self._changed.add('label')

    @property
    def comment(self) -> Optional[LangString]:
        return self._comment

    @comment.setter
    def comment(self, value: Optional[LangString]) -> None:
        if value is None:
            self._comment.empty()  # clear all comments!
        else:
            if isinstance(value, LangString):
                self._comment = value
            elif isinstance(value, str):
                self._comment = LangString(value)
            else:
                raise BaseError('Not a valid LangString')
        self._changed.add('comment')

    def addComment(self, lang: Union[Languages, str], value: str) -> None:
        self._comment[lang] = value
        self._changed.add('comment')

    def rmComment(self, lang: Union[Languages, str]) -> None:
        del self._comment[lang]
        self._changed.add('comment')

    @property
    def permissions(self) -> Optional[str]:
        return self._permissions

    @permissions.setter
    def permissions(self, value: str) -> None:
        raise BaseError('"permissions" cannot be modified!')

    @property
    def has_property(self) -> Dict[str, HasProperty]:
        return self._has_properties

    @has_property.setter
    def has_property(self, value: str) -> None:
        raise BaseError('"has_property" cannot be modified!')

    def getProperty(self, property_id) -> Optional[HasProperty]:
        if self._has_properties is None:
            return None
        else:
            return self._has_properties.get(
                self._context.getPrefixIri(property_id))

    def addProperty(
        self, property_id: str, cardinality: Cardinality,
        last_modification_date: LastModificationDate
    ) -> Optional[LastModificationDate]:
        if self._has_properties.get(property_id) is None:
            latest_modification_date, resclass = HasProperty(
                con=self.con,
                context=self._context,
                ontology_id=self._ontology_id,
                property_id=property_id,
                resclass_id=self.id,
                cardinality=cardinality).create(last_modification_date)
            hp = resclass.getProperty(property_id)
            hp.ontology_id = self._context.iriFromPrefix(self._ontology_id)
            hp.resclass_id = self.id
            self._has_properties[hp.property_id] = hp
            return latest_modification_date
        else:
            raise BaseError("Property already has cardinality in this class!")

    def updateProperty(
        self, property_id: str, cardinality: Cardinality,
        last_modification_date: LastModificationDate
    ) -> Optional[LastModificationDate]:
        property_id = self._context.getPrefixIri(property_id)
        if self._has_properties.get(property_id) is not None:
            has_properties = self._has_properties[property_id]
            onto_id = has_properties.ontology_id  # save for later user
            rescl_id = has_properties.resclass_id  # save for later user
            has_properties.cardinality = cardinality
            latest_modification_date, resclass = has_properties.update(
                last_modification_date)
            hp = resclass.getProperty(property_id)
            hp.ontology_id = self._context.iriFromPrefix(
                onto_id)  # restore value
            hp.resclass_id = rescl_id  # restore value
            self._has_properties[hp.property_id] = hp
            return latest_modification_date
        else:
            return last_modification_date

    @classmethod
    def fromJsonObj(cls, con: Connection, context: Context,
                    json_obj: Any) -> Any:
        if isinstance(json_obj, list):
            json_obj = json_obj[
                0]  # TODO: Is it possible to have more than one element in the list??
        if not isinstance(con, Connection):
            raise BaseError(
                '"con"-parameter must be an instance of Connection')
        if not isinstance(context, Context):
            raise BaseError(
                '"context"-parameter must be an instance of Context')
        rdf = context.prefixFromIri(
            "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
        rdfs = context.prefixFromIri("http://www.w3.org/2000/01/rdf-schema#")
        owl = context.prefixFromIri("http://www.w3.org/2002/07/owl#")
        xsd = context.prefixFromIri("http://www.w3.org/2001/XMLSchema#")
        knora_api = context.prefixFromIri(
            "http://api.knora.org/ontology/knora-api/v2#")
        salsah_gui = context.prefixFromIri(
            "http://api.knora.org/ontology/salsah-gui/v2#")

        if not (json_obj.get(knora_api + ':isResourceClass')
                or json_obj.get(knora_api + ':isStandoffClass')):
            raise BaseError("This is not a resource!")

        if json_obj.get('@id') is None:
            raise BaseError('Resource class has no "@id"!')
        tmp_id = json_obj.get('@id').split(':')
        id = context.iriFromPrefix(tmp_id[0]) + '#' + tmp_id[1]
        ontology_id = tmp_id[0]
        name = tmp_id[1]
        superclasses_obj = json_obj.get(rdfs + ':subClassOf')
        if superclasses_obj is not None:
            supercls: List[Any] = list(
                filter(lambda a: a.get('@id') is not None, superclasses_obj))
            superclasses: List[str] = list(map(lambda a: a['@id'], supercls))
            has_props: List[Any] = list(
                filter(lambda a: a.get('@type') == (owl + ':Restriction'),
                       superclasses_obj))
            has_properties: Dict[HasProperty] = dict(
                map(lambda a: HasProperty.fromJsonObj(con, context, a),
                    has_props))
        else:
            superclasses = None
            has_properties = None

        label = LangString.fromJsonLdObj(json_obj.get(rdfs + ':label'))
        comment = LangString.fromJsonLdObj(json_obj.get(rdfs + ':comment'))
        return cls(con=con,
                   context=context,
                   name=name,
                   id=id,
                   ontology_id=ontology_id,
                   superclasses=superclasses,
                   label=label,
                   comment=comment,
                   has_properties=has_properties)

    def toJsonObj(self,
                  lastModificationDate: LastModificationDate,
                  action: Actions,
                  what: Optional[str] = None) -> Any:
        def resolve_resref(resref: str):
            tmp = resref.split(':')
            if len(tmp) > 1:
                if tmp[0]:
                    return {
                        "@id": resref
                    }  # fully qualified name in the form "prefix:name"
                else:
                    return {
                        "@id":
                        self._context.prefixFromIri(self._ontology_id) + ':' +
                        tmp[1]
                    }  # ":name" in current ontology
            else:
                return {
                    "@id": "knora-api:" + resref
                }  # no ":", must be from knora-api!

        tmp = {}
        exp = re.compile('^http.*')  # It is already a fully IRI
        if exp.match(self._ontology_id):
            resid = self._context.prefixFromIri(
                self._ontology_id) + ":" + self._name
            ontid = self._ontology_id
        else:
            resid = self._ontology_id + ":" + self._name
            ontid = self._context.iriFromPrefix(self._ontology_id)
        if action == Actions.Create:
            if self._name is None:
                raise BaseError("There must be a valid resource class name!")
            if self._ontology_id is None:
                raise BaseError("There must be a valid ontology_id given!")
            if self._superclasses is None:
                superclasses = [{"@id": "knora-api:Resource"}]
            else:
                superclasses = list(map(resolve_resref, self._superclasses))
            if self._comment is None or self._comment.isEmpty():
                self._comment = LangString("no comment vailable")
            tmp = {
                "@id":
                ontid,  # self._ontology_id,
                "@type":
                "owl:Ontology",
                "knora-api:lastModificationDate":
                lastModificationDate.toJsonObj(),
                "@graph": [{
                    "@id": resid,
                    "@type": "owl:Class",
                    "rdfs:label": self._label.toJsonLdObj(),
                    "rdfs:comment": self._comment.toJsonLdObj(),
                    "rdfs:subClassOf": superclasses
                }],
                "@context":
                self._context.toJsonObj(),
            }
        elif action == Actions.Update:
            tmp = {
                "@id": ontid,  # self._ontology_id,
                "@type": "owl:Ontology",
                "knora-api:lastModificationDate":
                lastModificationDate.toJsonObj(),
                "@graph": [{
                    "@id": resid,
                    "@type": "owl:Class",
                }],
                "@context": self._context.toJsonObj(),
            }
            if what == 'label':
                if not self._label.isEmpty() and 'label' in self._changed:
                    tmp['@graph'][0]['rdfs:label'] = self._label.toJsonLdObj()
            if what == 'comment':
                if not self._comment.isEmpty() and 'comment' in self._changed:
                    tmp['@graph'][0][
                        'rdfs:comment'] = self._comment.toJsonLdObj()
        return tmp

    def create(
        self, last_modification_date: LastModificationDate
    ) -> Tuple[LastModificationDate, 'ResourceClass']:
        jsonobj = self.toJsonObj(last_modification_date, Actions.Create)
        jsondata = json.dumps(jsonobj)
        result = self.con.post('/v2/ontologies/classes', jsondata)
        last_modification_date = LastModificationDate(
            result['knora-api:lastModificationDate'])
        return last_modification_date, ResourceClass.fromJsonObj(
            self.con, self._context, result['@graph'])

    def update(
        self, last_modification_date: LastModificationDate
    ) -> Tuple[LastModificationDate, 'ResourceClass']:
        #
        # Note: Knora is able to change only one thing per call, either label or comment!
        #
        result = None
        something_changed = False
        if 'label' in self._changed:
            jsonobj = self.toJsonObj(last_modification_date, Actions.Update,
                                     'label')
            jsondata = json.dumps(jsonobj, cls=SetEncoder, indent=4)
            result = self.con.put('v2/ontologies/classes', jsondata)
            last_modification_date = LastModificationDate(
                result['knora-api:lastModificationDate'])
            something_changed = True
        if 'comment' in self._changed:
            jsonobj = self.toJsonObj(last_modification_date, Actions.Update,
                                     'comment')
            jsondata = json.dumps(jsonobj, cls=SetEncoder, indent=4)
            result = self.con.put('v2/ontologies/classes', jsondata)
            last_modification_date = LastModificationDate(
                result['knora-api:lastModificationDate'])
            something_changed = True
        if something_changed:
            return last_modification_date, ResourceClass.fromJsonObj(
                self.con, self._context, result['@graph'])
        else:
            return last_modification_date, self

    def delete(
            self, last_modification_date: LastModificationDate
    ) -> LastModificationDate:
        result = self.con.delete('v2/ontologies/classes/' +
                                 quote_plus(self._id) +
                                 '?lastModificationDate=' +
                                 str(last_modification_date))
        return LastModificationDate(result['knora-api:lastModificationDate'])

    def print(self, offset: int = 0):
        blank = ' '
        print(f'{blank:>{offset}}Resource Class Info')
        print(f'{blank:>{offset+2}}Name:            {self._name}')
        print(f'{blank:>{offset+2}}Ontology prefix: {self._ontology_id}')
        print(f'{blank:>{offset+2}}Superclasses:')
        if self._superclasses is not None:
            for sc in self._superclasses:
                print(f'{blank:>{offset + 4}}{sc}')
        if self._label is not None:
            print(f'{blank:>{offset + 2}}Labels:')
            self._label.print(offset + 4)
        if self._comment is not None:
            print(f'{blank:>{offset + 2}}Comments:')
            self._comment.print(offset + 4)
        if self._has_properties is not None:
            print(f'{blank:>{offset + 2}}Has properties:')
            if self._has_properties is not None:
                for pid, hp in self._has_properties.items():
                    hp.print(offset + 4)