예제 #1
0
    def test_langstring_tojson(self) -> None:
        """Test converting a LangString to JSON and JSON-LD"""
        ls = LangString(self.simple_string_de)
        json = ls.toJsonObj()
        self.assertEqual(json, self.simple_string_de)
        json = ls.toJsonLdObj()
        self.assertEqual(json, self.simple_string_de)

        ls = LangString({
            Languages.DE: self.simple_string_de,
            Languages.FR: self.simple_string_fr
        })
        json = ls.toJsonObj()
        expected = [{
            'language': 'de',
            'value': self.simple_string_de
        }, {
            'language': 'fr',
            'value': self.simple_string_fr
        }]
        self.assertEqual(json, expected)
        jsonld = ls.toJsonLdObj()
        expected = [{
            '@language': 'de',
            '@value': self.simple_string_de
        }, {
            '@language': 'fr',
            '@value': self.simple_string_fr
        }]
        self.assertEqual(jsonld, expected)
예제 #2
0
 def test_ListNode_create(self) -> None:
     """
     Create a list node
     :return: None
     """
     node = ListNode(con=self.con,
                     project=self.project,
                     label=LangString({Languages.DE: "root node 1"}),
                     comments=LangString({Languages.DE: "first root node"}),
                     name="test_node_1").create()
     self.assertIsNotNone(node.id)
     self.assertEqual(node.project, self.project)
     self.assertEqual(node.label['de'], "root node 1")
     self.assertEqual(node.comments['de'], "first root node")
     self.assertEqual(node.name, "test_node_1")
     self.assertTrue(node.isRootNode)
예제 #3
0
    def test_project_update(self) -> None:
        project = Project(con=self.con,
                          shortcode='0FF1',
                          shortname="update_project",
                          longname="Update Project",
                          description=LangString({
                              Languages.EN: 'Project to be updated',
                              Languages.DE: 'Update-Projekt'
                          }),
                          keywords={'test', 'project'},
                          selfjoin=False,
                          status=True,
                          logo=self.logo_file).create()

        project.shortname = "update_project"
        project.longname = "Update Project"
        project.addDescription('fr', 'Projet modifié')
        project.rmDescription('de')
        project.selfjoin = True
        project.status = False
        project.rmKeyword('project')
        project.addKeyword('updated')
        updated_project = project.update()

        self.assertEqual(updated_project.shortcode, '0FF1')
        self.assertEqual(updated_project.shortname, 'update_project')
        self.assertEqual(updated_project.longname, 'Update Project')
        self.assertEqual(updated_project.description['en'],
                         'Project to be updated')
        self.assertEqual(updated_project.description['fr'], 'Projet modifié')
        self.assertEqual(updated_project.selfjoin, True)
        self.assertEqual(updated_project.status, False)
        self.assertEqual(updated_project.keywords, {'test', 'updated'})
예제 #4
0
    def test_Project(self) -> None:
        project = Project(con=self.con,
                          id='http://rdfh.ch/test',
                          shortcode='0FF0',
                          shortname="test_project",
                          longname="Test Project",
                          description=LangString({
                              Languages.EN:
                              'This is a test project',
                              Languages.DE:
                              'Das ist ein Testprojekt'
                          }),
                          keywords={'test', 'project'},
                          selfjoin=False,
                          status=True,
                          logo=self.logo_file)

        self.assertIsNotNone(project)
        self.assertEqual(project.id, 'http://rdfh.ch/test')
        self.assertEqual(project.shortcode, '0FF0')
        self.assertEqual(project.shortname, 'test_project')
        self.assertEqual(project.longname, 'Test Project')
        self.assertEqual(project.description['en'], 'This is a test project')
        self.assertEqual(project.description['de'], 'Das ist ein Testprojekt')
        self.assertEqual(project.selfjoin, False)
        self.assertEqual(project.status, True)
        self.assertEqual(project.keywords, {'test', 'project'})
예제 #5
0
    def test_project_delete(self) -> None:
        project = Project(con=self.con,
                          shortcode='0FF2',
                          shortname="delete_project",
                          longname="Delete Project",
                          description=LangString({
                              Languages.EN: 'Project to be deleted',
                              Languages.DE: 'Lösch-Projekt'
                          }),
                          keywords={'test', 'project', 'delete'},
                          selfjoin=False,
                          status=True,
                          logo=self.logo_file).create()

        deleted_project = project.delete()

        self.assertEqual(deleted_project.shortcode, '0FF2')
        self.assertEqual(deleted_project.shortname, 'delete_project')
        self.assertEqual(deleted_project.longname, 'Delete Project')
        self.assertEqual(deleted_project.description['en'],
                         'Project to be deleted')
        self.assertEqual(deleted_project.description['de'], 'Lösch-Projekt')
        self.assertEqual(deleted_project.selfjoin, False)
        self.assertEqual(deleted_project.status, False)
        self.assertEqual(deleted_project.keywords,
                         {'test', 'project', 'delete'})
예제 #6
0
 def fromJsonObj(cls, con: Connection, json_obj: Any):
     id = json_obj.get('id')
     if id is None:
         raise BaseError('Group "id" is missing')
     name = json_obj.get('name')
     if name is None:
         raise BaseError('Group "name" is missing')
     descriptions = LangString.fromJsonObj(json_obj.get('descriptions'))
     tmp = json_obj.get('project')
     if tmp is None:
         raise BaseError('Group "project" is missing')
     project = tmp.get('id')
     if project is None:
         raise BaseError('Group "project" has no "id"')
     selfjoin = json_obj.get('selfjoin')
     if selfjoin is None:
         raise BaseError("selfjoin is missing")
     status = json_obj.get('status')
     if status is None:
         raise BaseError("Status is missing")
     return cls(con=con,
                name=name,
                id=id,
                descriptions=descriptions,
                project=project,
                selfjoin=selfjoin,
                status=status)
예제 #7
0
    def test_Group_update(self) -> None:
        """
        Update an existing group
        :return: None
        """
        group = Group(con=self.con,
                      name="Group update",
                      descriptions=LangString(
                          {Languages.EN: 'This is group update'}),
                      project=self.test_project,
                      status=True,
                      selfjoin=False).create()

        group.name = "Group update - modified"
        group.descriptions = {"en": "This is group update - modified"}
        group.selfjoin = True
        group.status = False
        updated_group = group.update()

        self.assertEqual(updated_group.name, 'Group update - modified')
        self.assertCountEqual(updated_group.descriptions.toJsonObj(),
                              [{
                                  'language': 'en',
                                  'value': 'This is group '
                                  'update - '
                                  'modified'
                              }])
        self.assertEqual(updated_group.project, self.test_project)
        self.assertFalse(updated_group.status)
        self.assertTrue(updated_group.selfjoin)
예제 #8
0
def create_groups(con: Connection, groups: list[dict[str, str]], project: Project, verbose: bool) -> dict[str, Group]:
    """
    Creates group(s) on a DSP server from a list of group definitions

    Args:
        con: connection instance to connect to the DSP server
        groups: List of definitions of the groups (JSON) to be created
        project: Project the group(s) should be added to
        verbose: Prints out more information if set to True

    Returns:
        Dict with group names and groups
    """
    new_groups: dict[str, Group] = {}
    for group in groups:
        group_name = group["name"]

        # check if the group already exists, skip if so
        all_groups: Optional[list[Group]] = Group.getAllGroups(con)
        group_exists: bool = False
        if all_groups:
            for group_item in all_groups:
                if group_item.project == project.id and group_item.name == group_name:
                    group_exists = True
        if group_exists:
            print(f"WARN Group '{group_name}' already exists. Skipping...")
            continue

        # check if status is defined, set default value if not
        group_status: Optional[str] = group.get("status")
        group_status_bool = True
        if isinstance(group_status, str):
            group_status_bool = json.loads(group_status.lower())  # lower() converts string to boolean

        # check if selfjoin is defined, set default value if not
        group_selfjoin: Optional[str] = group.get("selfjoin")
        group_selfjoin_bool = False
        if isinstance(group_selfjoin, str):
            group_selfjoin_bool = json.loads(group_selfjoin.lower())  # lower() converts string to boolean

        # create the group
        try:
            new_group: Group = Group(con=con,
                                     name=group_name,
                                     descriptions=LangString(group["descriptions"]),
                                     project=project,
                                     status=group_status_bool,
                                     selfjoin=group_selfjoin_bool).create()
            if verbose:
                print(f"Created group '{group_name}'.")
            if new_group.name:
                new_groups[new_group.name] = new_group

        except BaseError as err:
            print(f"ERROR while trying to create group '{group_name}'. The error message was: {err.message}")
            exit(1)
        except Exception as exception:
            print(f"ERROR while trying to create group '{group_name}'. The error message was: {exception}")
            exit(1)
    return new_groups
예제 #9
0
def create_project(con: Connection, data_model: dict[str, Any], verbose: bool) -> Project:
    """
    Creates a project on a DSP server with information provided in the data_model

    Args:
        con: connection instance to connect to the DSP server
        data_model: The data model as JSON
        verbose: Prints out more information if set to True

    Returns:
        created project
    """
    project_shortcode = data_model["project"]["shortcode"]
    project_shortname = data_model["project"]["shortname"]

    try:
        project = Project(con=con,
                          shortcode=data_model["project"]["shortcode"],
                          shortname=data_model["project"]["shortname"],
                          longname=data_model["project"]["longname"],
                          description=LangString(data_model["project"].get("descriptions")),
                          keywords=set(data_model["project"].get("keywords")),
                          selfjoin=False,
                          status=True).create()
        if verbose:
            print(f"Created project '{project_shortname}' ({project_shortcode}).")
        return project
    except BaseError as err:
        print(
            f"ERROR while trying to create project '{project_shortname}' ({project_shortcode}). The error message was: {err.message}")
        exit(1)
    except Exception as exception:
        print(
            f"ERROR while trying to create project '{project_shortname}' ({project_shortcode}). The error message was: {exception}")
        exit(1)
예제 #10
0
 def test_langstring_instantiation3(self) -> None:
     """Test a LangString using string and Languages-enums as index."""
     ls = LangString({
         Languages.DE: self.simple_string_de,
         Languages.FR: self.simple_string_fr
     })
     self.assertEqual(ls[Languages.DE], self.simple_string_de)
     self.assertEqual(ls['fr'], self.simple_string_fr)
예제 #11
0
 def __init__(self,
              con: Connection,
              id: Optional[str] = None,
              name: Optional[str] = None,
              descriptions: LangString = None,
              project: Optional[Union[str, Project]] = None,
              selfjoin: Optional[bool] = None,
              status: Optional[bool] = None):
     super().__init__(con)
     self._id = str(id) if id is not None else None
     self._name = str(name) if name is not None else None
     self._descriptions = LangString(descriptions)
     if project is not None and isinstance(project, Project):
         self._project = project.id
     else:
         self._project = str(project) if project is not None else None
     self._selfjoin = bool(selfjoin) if selfjoin is not None else None
     self._status = bool(status) if status is not None else None
예제 #12
0
 def test_langstring_change(self) -> None:
     """test if changing a LangString item works."""
     ls = LangString({
         Languages.DE: self.simple_string_de,
         Languages.FR: self.simple_string_fr
     })
     ls['de'] = 'gagaga'
     self.assertEqual(ls[Languages.DE], 'gagaga')
     self.assertEqual(ls['fr'], self.simple_string_fr)
예제 #13
0
 def test_ListNode_update(self) -> None:
     """
     Update the data of a node
     :return: None
     """
     node = ListNode(con=self.con,
                     project=self.project,
                     label=LangString({Languages.EN: "root node 3"}),
                     comments=LangString({Languages.EN: "Third root node"}),
                     name="test_node").create()
     node.addLabel('de', "Neues Label")
     node.rmLabel('en')
     node.addComment('fr', 'un commentaire en français')
     node.rmComment('en')
     node.name = 'test_node_update'
     node.update()
     self.assertEqual(node.label['de'], "Neues Label")
     self.assertEqual(node.comments['fr'], 'un commentaire en français')
     self.assertEqual(node.name, 'test_node_update')
예제 #14
0
 def test_ListNode_hierarchy(self) -> None:
     """
     Create a node and a sub-node
     :return: None
     """
     node = ListNode(con=self.con,
                     project=self.project,
                     label=LangString({Languages.EN: "root node"}),
                     comments=LangString(
                         {Languages.EN: "This is a root node"}),
                     name="root_node").create()
     subnode = ListNode(
         con=self.con,
         project=self.project,
         label=LangString({Languages.DE: 'Ein Knoten der Liste'}),
         comments=LangString({Languages.DE: "Ein Kommentar"}),
         name="sub_node",
         parent=node).create()
     self.assertTrue(node.isRootNode)
     self.assertFalse(subnode.isRootNode)
예제 #15
0
 def test_langstring_iterator(self) -> None:
     """Test iterating over a LangString."""
     ls = LangString({
         Languages.DE: self.simple_string_de,
         Languages.FR: self.simple_string_fr
     })
     for tmp in ls:
         if tmp[0] == Languages.DE:
             self.assertEqual(tmp[1], self.simple_string_de)
         elif tmp[0] == Languages.FR:
             self.assertEqual(tmp[1], self.simple_string_fr)
예제 #16
0
 def test_langstring_fromjsonld(self) -> None:
     """Test reading a LangString from JSON-LD as used in Knora data/ontologies"""
     test = [{
         '@language': 'en',
         '@value': self.test_string_en
     }, {
         '@language': 'de',
         '@value': self.test_string_de
     }]
     ls = LangString.fromJsonLdObj(test)
     self.assertEqual(ls['de'], self.test_string_de)
     self.assertEqual(ls[Languages.EN], self.test_string_en)
예제 #17
0
 def test_langstring_fromjson(self) -> None:
     """Test reading a LangString from JSON as used in Knora Admin."""
     test = [{
         'language': 'en',
         'value': self.test_string_en
     }, {
         'language': 'de',
         'value': self.test_string_de
     }]
     ls = LangString.fromJsonObj(test)
     self.assertEqual(ls['de'], self.test_string_de)
     self.assertEqual(ls[Languages.EN], self.test_string_en)
예제 #18
0
    def test_group_create(self) -> None:
        """
        Create a group
        :return: None
        """
        group = Group(con=self.con,
                      name="Group create",
                      descriptions=LangString(
                          {Languages.EN: 'This is group create'}),
                      project=self.test_project,
                      status=True,
                      selfjoin=False)

        self.assertEqual(group.name, 'Group create')
        self.assertCountEqual(group.descriptions.toJsonObj(),
                              [{
                                  'language': 'en',
                                  'value': 'This is group create'
                              }])
        self.assertEqual(group.project, self.test_project)
        self.assertTrue(group.status)
        self.assertFalse(group.selfjoin)
예제 #19
0
 def test_project_create(self) -> None:
     project = Project(con=self.con,
                       shortcode='0FF0',
                       shortname="new_project",
                       longname="New test project",
                       description=LangString({
                           Languages.EN: 'New project',
                           Languages.DE: 'Neues Projekt'
                       }),
                       keywords={'test', 'project', 'new'},
                       selfjoin=False,
                       status=True,
                       logo=self.logo_file)
     new_project = project.create()
     self.assertIsNotNone(new_project)
     self.assertEqual(new_project.shortcode, '0FF0')
     self.assertEqual(new_project.shortname, 'new_project')
     self.assertEqual(new_project.longname, 'New test project')
     self.assertEqual(new_project.description['en'], 'New project')
     self.assertEqual(new_project.description['de'], 'Neues Projekt')
     self.assertEqual(new_project.keywords, {'test', 'project', 'new'})
     self.assertEqual(new_project.selfjoin, False)
     self.assertEqual(new_project.status, True)
     self.assertEqual(new_project.keywords, {'test', 'project', 'new'})
예제 #20
0
    def test_Group_delete(self) -> None:
        """
        Mark an existing group as deleted (it will not be deleted completely from the triplestore, but status set to
        False)
        :return: None
        """
        group = Group(con=self.con,
                      name="Group delete",
                      descriptions=LangString(
                          {Languages.EN: 'This is group delete'}),
                      project=self.test_project,
                      status=True,
                      selfjoin=False).create()

        deleted_group = group.delete()
        self.assertEqual(deleted_group.name, 'Group delete')
        self.assertCountEqual(deleted_group.descriptions.toJsonObj(),
                              [{
                                  'language': 'en',
                                  'value': 'This is group delete'
                              }])
        self.assertEqual(deleted_group.project, self.test_project)
        self.assertFalse(deleted_group.status)
        self.assertFalse(deleted_group.selfjoin)
예제 #21
0
class TestResourceClass(unittest.TestCase):
    test_project = "http://rdfh.ch/projects/0001"

    res_name = 'res_class_name'
    res_label = LangString({Languages.EN: 'Resource Class Label'})
    res_comment = LangString(
        {Languages.EN: 'This is a resource class for testing'})

    def setUp(self) -> None:
        """
        is executed before all tests; sets up a connection and logs in as user root
        """
        self.con = Connection('http://0.0.0.0:3333')
        self.con.login('*****@*****.**', 'test')

    def test_ResourceClass_create(self) -> None:
        onto = Ontology(
            con=self.con,
            project=self.test_project,
            name='test_onto',
            label='Test Ontology',
        ).create()

        last_modification_date_onto = onto.lastModificationDate

        # create test resource class
        last_modification_date_res, res_class = ResourceClass(
            con=self.con,
            context=onto.context,
            name=self.res_name,
            ontology_id=onto.id,
            label=self.res_label,
            comment=self.res_comment).create(last_modification_date_onto)

        self.assertIsNotNone(res_class.id)
        self.assertEqual(res_class.name, self.res_name)
        self.assertEqual(res_class.label['en'], self.res_label['en'])
        self.assertEqual(res_class.comment['en'], self.res_comment['en'])

    def test_ResourceClass_update(self) -> None:
        onto = Ontology(
            con=self.con,
            project=self.test_project,
            name='test_onto_2',
            label='Test Ontology 2',
        ).create()

        last_modification_date = onto.lastModificationDate

        # create test resource class
        last_modification_date, res_class = ResourceClass(
            con=self.con,
            context=onto.context,
            name=self.res_name,
            ontology_id=onto.id,
            label=self.res_label,
            comment=self.res_comment).create(last_modification_date)

        onto.lastModificationDate = last_modification_date

        self.assertIsNotNone(res_class.id)

        # modify the resource class
        res_class.addLabel('de', "Dies ist ein Kommentar")
        res_class.rmLabel('en')
        res_class.addComment('it', "Commentario italiano")

        last_modification_date, res_class = res_class.update(
            last_modification_date)
        self.assertEqual(res_class.label['de'], "Dies ist ein Kommentar")
        self.assertEqual(res_class.comment['it'], "Commentario italiano")

    def tearDown(self) -> None:
        """
        is executed after all tests are run through; performs a log out
        """
        self.con.logout()
예제 #22
0
def create_ontology(input_file: str,
                    lists_file: str,
                    server: str,
                    user_mail: str,
                    password: str,
                    verbose: bool,
                    dump: bool) -> None:
    """
    Creates the ontology and all its parts from a JSON input file on a DSP server

    Args:
        input_file: The input JSON file from which the ontology and its parts should be created
        lists_file: The file which the list output (list node ID) is written to
        server: The DSP server which the ontology should be created on
        user_mail: The user (e-mail) which the ontology should be created with (requesting user)
        password: The password for the user (requesting user)
        verbose: Prints more information if set to True
        dump: Dumps test files (JSON) for DSP API requests if set to True

    Returns:
        None
    """

    knora_api_prefix = "knora-api:"

    # read the ontology from the input file
    with open(input_file) as f:
        onto_json_str = f.read()

    data_model = json.loads(onto_json_str)

    # expand all lists referenced in the list section of the data model and add them to the ontology
    data_model["project"]["lists"] = expand_lists_from_excel(data_model)

    # validate the ontology
    if not validate_ontology(data_model):
        exit(1)

    # make the connection to the server
    con = login(server=server, user=user_mail, password=password)

    if dump:
        con.start_logging()

    # read the prefixes of external ontologies that may be used
    context = Context(data_model.get("prefixes") or {})

    # check if the project exists
    project = None
    try:
        project = Project(con=con, shortcode=data_model["project"]["shortcode"]).read()
    except BaseError:
        pass

    # if project exists, update it
    if project:
        print(f"Project '{data_model['project']['shortcode']}' already exists. Updating it...")
        updated_project: Project = update_project(project=project, data_model=data_model, verbose=verbose)
        if verbose:
            updated_project.print()

    # if project does not exist, create it
    else:
        if verbose:
            print("Create project...")
        project = create_project(con=con, data_model=data_model, verbose=verbose)

    # create the list(s), skip if it already exists
    list_root_nodes = {}
    if data_model["project"].get("lists"):
        if verbose:
            print("Create lists...")
        list_root_nodes = create_lists(input_file, lists_file, server, user_mail, password, verbose)

    # create the group(s), skip if it already exists
    new_groups = {}
    if data_model["project"].get("groups"):
        if verbose:
            print("Create groups...")
        new_groups = create_groups(con=con, groups=data_model["project"]["groups"], project=project, verbose=verbose)

    # create or update the user(s), skip if it already exists
    if data_model["project"].get("users"):
        if verbose:
            print("Create users...")
        create_users(con=con, users=data_model["project"]["users"], groups=new_groups, project=project,
                     verbose=verbose)

    # create the ontologies
    if verbose:
        print("Create ontologies...")
    for ontology in data_model.get("project").get("ontologies"):
        new_ontology = None
        last_modification_date = None
        ontology_name = ontology["name"]
        try:
            new_ontology = Ontology(con=con,
                                    project=project,
                                    label=ontology["label"],
                                    name=ontology_name).create()
            last_modification_date = new_ontology.lastModificationDate
            if verbose:
                print(f"Created ontology '{ontology_name}'.")
        except BaseError as err:
            print(
                f"ERROR while trying to create ontology '{ontology_name}'. The error message was {err.message}")
            exit(1)
        except Exception as exception:
            print(f"ERROR while trying to create ontology '{ontology_name}'. The error message was {exception}")
            exit(1)

        # add the prefixes defined in the json file
        for prefix, ontology_info in context:
            if prefix not in new_ontology.context and ontology_info:
                s = ontology_info.iri + ("#" if ontology_info.hashtag else "")
                new_ontology.context.add_context(prefix, s)

        # create the empty resource classes
        new_res_classes: dict[str, ResourceClass] = {}
        for res_class in ontology.get("resources"):
            res_name = res_class.get("name")
            super_classes = res_class.get("super")
            if isinstance(super_classes, str):
                super_classes = [super_classes]
            res_label = LangString(res_class.get("labels"))
            res_comment = res_class.get("comments")
            if res_comment:
                res_comment = LangString(res_comment)
            else:
                res_comment = LangString({"en": "[no comment provided]"})
            # if no cardinalities are submitted, don't create the class
            if not res_class.get("cardinalities"):
                print(f"ERROR while trying to add cardinalities to class '{res_name}'. No cardinalities submitted. At"
                      f"least one direct cardinality is required to create a class with dsp-tools.")
                continue

            new_res_class: Optional[ResourceClass] = None
            try:
                last_modification_date, new_res_class = ResourceClass(con=con,
                                                                      context=new_ontology.context,
                                                                      ontology_id=new_ontology.id,
                                                                      name=res_name,
                                                                      superclasses=super_classes,
                                                                      label=res_label,
                                                                      comment=res_comment).create(
                    last_modification_date)
            except BaseError as err:
                print(
                    f"ERROR while trying to create resource class {res_name}. The error message was {err.message}")
            except Exception as exception:
                print(
                    f"ERROR while trying to create resource class {res_name}. The error message was {exception}")

            if new_res_class:
                if isinstance(new_res_class.id, str):
                    new_res_classes[new_res_class.id] = new_res_class
                new_ontology.lastModificationDate = last_modification_date

                if verbose:
                    print("Created resource class:")
                    new_res_class.print()

        # create the property classes
        for prop_class in ontology.get("properties"):
            prop_name = prop_class.get("name")
            prop_label = LangString(prop_class.get("labels"))

            # get the super-property/ies if defined, valid forms are:
            #   - "prefix:super-property" : fully qualified name of property in another ontology. The prefix has to be
            #     defined in the prefixes part.
            #   - "super-property" : super-property defined in the knora-api ontology
            #   - if omitted, "knora-api:hasValue" is assumed

            if prop_class.get("super"):
                super_props = []
                for super_class in prop_class.get("super"):
                    if ':' in super_class:
                        super_props.append(super_class)
                    else:
                        super_props.append(knora_api_prefix + super_class)
            else:
                super_props = ["knora-api:hasValue"]

            # get the "object" if defined, valid forms are:
            #   - "prefix:object_name" : fully qualified object. The prefix has to be defined in the prefixes part.
            #   - ":object_name" : The object is defined in the current ontology.
            #   - "object_name" : The object is defined in "knora-api"

            if prop_class.get("object"):
                tmp_group_name = prop_class.get("object").split(':')
                if len(tmp_group_name) > 1:
                    if tmp_group_name[0]:
                        prop_object = prop_class.get("object")  # fully qualified name
                    else:
                        prop_object = new_ontology.name + ':' + tmp_group_name[1]  # object refers to actual ontology
                else:
                    prop_object = knora_api_prefix + prop_class.get("object")  # object refers to knora-api
            else:
                prop_object = None
            prop_subject = prop_class.get("subject")
            gui_element = prop_class.get("gui_element")
            gui_attributes = prop_class.get("gui_attributes")
            if gui_attributes and gui_attributes.get("hlist"):
                gui_attributes["hlist"] = "<" + list_root_nodes[gui_attributes["hlist"]]["id"] + ">"
            prop_comment = prop_class.get("comments")
            if prop_comment:
                prop_comment = LangString(prop_comment)
            else:
                prop_comment = LangString({"en": "[no comment provided]"})

            new_prop_class = None
            try:
                last_modification_date, new_prop_class = PropertyClass(con=con,
                                                                       context=new_ontology.context,
                                                                       label=prop_label,
                                                                       name=prop_name,
                                                                       ontology_id=new_ontology.id,
                                                                       superproperties=super_props,
                                                                       object=prop_object,
                                                                       subject=prop_subject,
                                                                       gui_element="salsah-gui:" + gui_element,
                                                                       gui_attributes=gui_attributes,
                                                                       comment=prop_comment).create(
                    last_modification_date)
            except BaseError as err:
                print(
                    f"ERROR while trying to create property class {prop_name}. The error message was: {err.message}"
                )
            except Exception as exception:
                print(
                    f"ERROR while trying to create property class {prop_name}. The error message was: {exception}")

            if new_prop_class:
                new_ontology.lastModificationDate = last_modification_date
                if verbose:
                    print("Created property:")
                    new_prop_class.print()

        # Add cardinalities to class
        switcher = {
            "1": Cardinality.C_1,
            "0-1": Cardinality.C_0_1,
            "0-n": Cardinality.C_0_n,
            "1-n": Cardinality.C_1_n
        }

        for res_class in ontology.get("resources"):
            if res_class.get("cardinalities"):
                for card_info in res_class.get("cardinalities"):
                    rc = new_res_classes.get(new_ontology.id + "#" + res_class.get("name"))
                    cardinality = switcher[card_info.get("cardinality")]
                    prop_name_for_card = card_info.get("propname")
                    tmp_group_name = prop_name_for_card.split(":")
                    if len(tmp_group_name) > 1:
                        if tmp_group_name[0]:
                            prop_id = prop_name_for_card  # fully qualified name
                        else:
                            prop_id = new_ontology.name + ":" + tmp_group_name[1]  # prop name refers to actual ontology
                    else:
                        prop_id = knora_api_prefix + prop_name_for_card  # prop name refers to knora-api

                    if rc:
                        try:
                            last_modification_date = rc.addProperty(
                                property_id=prop_id,
                                cardinality=cardinality,
                                gui_order=card_info.get("gui_order"),
                                last_modification_date=last_modification_date)

                        except BaseError as err:
                            print(
                                f"ERROR while trying to add cardinality {prop_id} to resource class {res_class.get('name')}."
                                f"The error message was {err.message}")
                        except Exception as exception:
                            print(
                                f"ERROR while trying to add cardinality {prop_id} to resource class {res_class.get('name')}."
                                f"The error message was {exception}")

                        new_ontology.lastModificationDate = last_modification_date
예제 #23
0
 def descriptions(self, value: Optional[LangString]) -> None:
     self._descriptions = LangString(value)
     self._changed.add('descriptions')
예제 #24
0
class Group(Model):
    """
    This class represents a Knora group

    Attributes
    ----------

    con : Connection
        A connection instance to a Knora server

    id : str
        IRI of the group [get only, cannot be modified after creation of instance]

    name : str
        Name of the group

    descriptions : LangString
        Group descriptions in a given language (Languages.EN, Languages.DE, Languages.FR, Languages.IT).

    project : str | project
        either the IRI of a project [get only, cannot be modified after creation of instance]
        or an valid Project instance

    selfjoin : boolean
        A flag indicating if selfjoin is allowed in this group

    status : boolean
        A flag indicating if the group is active (True) or inactive/makred deleted (False)

    """

    PROJECT_MEMBER_GROUP: str = "http://www.knora.org/ontology/knora-admin#ProjectMember"
    PROJECT_ADMIN_GROUP: str = "http://www.knora.org/ontology/knora-admin#ProjectAdmin"
    PROJECT_SYSTEMADMIN_GROUP: str = "http://www.knora.org/ontology/knora-admin#SystemAdmin"
    ROUTE: str = "/admin/groups"
    ROUTE_SLASH: str = ROUTE + "/"

    _id: str
    _name: str
    _descriptions: LangString
    _project: str
    _selfjoin: bool
    _status: bool

    def __init__(self,
                 con: Connection,
                 id: Optional[str] = None,
                 name: Optional[str] = None,
                 descriptions: LangString = None,
                 project: Optional[Union[str, Project]] = None,
                 selfjoin: Optional[bool] = None,
                 status: Optional[bool] = None):
        super().__init__(con)
        self._id = str(id) if id is not None else None
        self._name = str(name) if name is not None else None
        self._descriptions = LangString(descriptions)
        if project is not None and isinstance(project, Project):
            self._project = project.id
        else:
            self._project = str(project) if project is not None else None
        self._selfjoin = bool(selfjoin) if selfjoin is not None else None
        self._status = bool(status) if status is not None else None

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

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

    @property
    def name(self) -> Optional[str]:
        return self._name

    @name.setter
    def name(self, value: str):
        self._name = value
        self._changed.add('name')

    @property
    def descriptions(self) -> Optional[LangString]:
        return self._descriptions

    @descriptions.setter
    def descriptions(self, value: Optional[LangString]) -> None:
        self._descriptions = LangString(value)
        self._changed.add('descriptions')

    @property
    def project(self):
        return self._project

    @project.setter
    def project(self, value: str):
        raise BaseError('project id cannot be modified!')

    @property
    def selfjoin(self) -> bool:
        return self._selfjoin

    @selfjoin.setter
    def selfjoin(self, value: bool) -> None:
        self._selfjoin = value
        self._changed.add('selfjoin')

    @property
    def status(self) -> bool:
        return self._status

    @status.setter
    def status(self, value: bool) -> None:
        self._status = value
        self._changed.add('status')

    def has_changed(self) -> bool:
        if self._changed:
            return True
        else:
            return False

    @classmethod
    def fromJsonObj(cls, con: Connection, json_obj: Any):
        id = json_obj.get('id')
        if id is None:
            raise BaseError('Group "id" is missing')
        name = json_obj.get('name')
        if name is None:
            raise BaseError('Group "name" is missing')
        descriptions = LangString.fromJsonObj(json_obj.get('descriptions'))
        tmp = json_obj.get('project')
        if tmp is None:
            raise BaseError('Group "project" is missing')
        project = tmp.get('id')
        if project is None:
            raise BaseError('Group "project" has no "id"')
        selfjoin = json_obj.get('selfjoin')
        if selfjoin is None:
            raise BaseError("selfjoin is missing")
        status = json_obj.get('status')
        if status is None:
            raise BaseError("Status is missing")
        return cls(con=con,
                   name=name,
                   id=id,
                   descriptions=descriptions,
                   project=project,
                   selfjoin=selfjoin,
                   status=status)

    def toJsonObj(self, action: Actions):
        tmp = {}
        if action == Actions.Create:
            if self._name is None:
                raise BaseError("There must be a valid name!")
            tmp['name'] = self._name
            if not self._descriptions.isEmpty():
                tmp['descriptions'] = self._descriptions.toJsonObj()
            if self._project is None:
                raise BaseError("There must be a valid project!")
            tmp['project'] = self._project
            if self._selfjoin is None:
                raise BaseError("There must be a valid value for selfjoin!")
            tmp['selfjoin'] = self._selfjoin
            if self._status is None:
                raise BaseError("There must be a valid value for status!")
            tmp['status'] = self._status
        else:
            if self._name is not None and 'name' in self._changed:
                tmp['name'] = self._name
            if not self._descriptions.isEmpty(
            ) and 'descriptions' in self._changed:
                tmp['descriptions'] = self._descriptions.toJsonObj()
            if self._selfjoin is not None and 'selfjoin' in self._changed:
                tmp['selfjoin'] = self._selfjoin
        return tmp

    def create(self) -> Group:
        jsonobj = self.toJsonObj(Actions.Create)
        jsondata = json.dumps(jsonobj)
        result = self._con.post(Group.ROUTE, jsondata)
        return Group.fromJsonObj(self._con, result['group'])

    def read(self):
        result = self._con.get(Group.ROUTE_SLASH + quote_plus(self._id))
        return Group.fromJsonObj(self._con, result['group'])

    def update(self):
        jsonobj = self.toJsonObj(Actions.Update)
        if jsonobj:
            jsondata = json.dumps(jsonobj)
            result = self._con.put(Group.ROUTE_SLASH + quote_plus(self._id),
                                   jsondata)
            updated_group = Group.fromJsonObj(self._con, result['group'])
        if self._status is not None and 'status' in self._changed:
            jsondata = json.dumps({'status': self._status})
            result = self._con.put(
                Group.ROUTE_SLASH + quote_plus(self._id) + '/status', jsondata)
            updated_group = Group.fromJsonObj(self._con, result['group'])
        return updated_group

    def delete(self):
        result = self._con.delete(Group.ROUTE_SLASH + quote_plus(self._id))
        return Group.fromJsonObj(self._con, result['group'])

    @staticmethod
    def getAllGroups(con: Connection) -> Optional[list[Group]]:
        try:
            result = con.get(Group.ROUTE)
            return [
                Group.fromJsonObj(con, group_item)
                for group_item in result["groups"]
            ]
        except BaseError:
            # return None if no groups are found or an error happened
            return None

    @staticmethod
    def getAllGroupsForProject(con: Connection,
                               proj_shortcode: str) -> list[Group]:
        result = con.get(Group.ROUTE)
        if 'groups' not in result:
            raise BaseError("Request got no groups!")
        all_groups = result["groups"]
        project_groups = []
        for group in all_groups:
            if group["project"][
                    "id"] == "http://rdfh.ch/projects/" + proj_shortcode:
                project_groups.append(group)
        return list(map(lambda a: Group.fromJsonObj(con, a), project_groups))

    def createDefinitionFileObj(self):
        group = {
            "name": self.name,
            "descriptions": self.descriptions.createDefinitionFileObj(),
            "selfjoin": self.selfjoin,
            "status": self.status
        }
        return group

    def print(self) -> None:
        print('Group Info:')
        print('  Id:          {}'.format(self._id))
        print('  Name:        {}'.format(self._name))
        if self._descriptions is not None:
            print('  Descriptions:')
            for descr in self._descriptions.items():
                print('    {}: {}'.format(descr[0], descr[1]))
        else:
            print('  Descriptions: None')
        print('  Project:     {}'.format(self._project))
        print('  Selfjoin:    {}'.format(self._selfjoin))
        print('  Status:      {}'.format(self._status))
예제 #25
0
 def test_langstring_instantiation1(self) -> None:
     """Test a LangString without language."""
     ls = LangString(self.simple_string_de)
     self.assertEqual(ls[None], self.simple_string_de)
예제 #26
0
 def test_langstring_emptyness(self) -> None:
     """Test if a LanGstring can be emptied and if the emptyness is detected."""
     ls = LangString()
     self.assertTrue(ls.isEmpty())
     ls = LangString(self.simple_string_de)
     ls.empty()
     self.assertTrue(ls.isEmpty())
     ls = LangString({
         Languages.DE: self.simple_string_de,
         Languages.FR: self.simple_string_fr
     })
     ls.empty()
     self.assertTrue(ls.isEmpty())
예제 #27
0
class TestPropertyClass(unittest.TestCase):
    project = "http://rdfh.ch/projects/0001"
    onto_name = 'propclass-test-a'
    onto_label = 'propclass_test_ontology'

    onto: Ontology
    last_modification_date: LastModificationDate
    con: Connection

    name = 'MyPropClassName'
    object = 'TextValue'
    label = LangString({Languages.DE: 'MyPropClassLabel'})
    comment = LangString(
        {Languages.DE: 'This is a property class for testing'})

    def setUp(self) -> None:
        """
        is executed before all tests; sets up a connection and logs in as user root; creates a new ontology
        """
        self.con = Connection('http://0.0.0.0:3333')
        self.con.login('*****@*****.**', 'test')

        # Create a test ontology
        self.onto = Ontology(
            con=self.con,
            project=self.project,
            name=self.onto_name,
            label=self.onto_label,
        ).create()

        self.assertIsNotNone(self.onto.id)
        self.last_modification_date = self.onto.lastModificationDate

    def tearDown(self) -> None:
        """
        is executed after all tests are run through; removes test ontology
        """
        result = self.onto.delete()
        self.assertIsNotNone(result)

    def test_PropertyClass_create(self) -> None:
        """
        create new property class
        """
        self.last_modification_date, property_class = PropertyClass(
            con=self.con,
            context=self.onto.context,
            name=self.name,
            ontology_id=self.onto.id,
            object=self.object,
            label=self.label,
            comment=self.comment).create(self.last_modification_date)

        self.onto.lastModificationDate = self.last_modification_date

        self.assertIsNotNone(property_class.id)
        self.assertEqual(property_class.name, self.name)
        self.assertEqual(property_class.label['de'], self.label['de'])
        self.assertEqual(property_class.comment['de'], self.comment['de'])

        # get ontology data
        self.onto = self.onto.read()
        self.last_modification_date = self.onto.lastModificationDate
        self.last_modification_date = property_class.delete(
            self.last_modification_date)

        # get ontology data
        self.onto = self.onto.read()

    def test_PropertyClass_update(self) -> None:
        self.onto = self.onto.read()

        # create test resource class
        self.last_modification_date, property_class = PropertyClass(
            con=self.con,
            context=self.onto.context,
            name=self.name,
            ontology_id=self.onto.id,
            object=self.object,
            label=self.label,
            comment=self.comment).create(self.last_modification_date)
        self.onto.lastModificationDate = self.last_modification_date
        self.assertIsNotNone(property_class.id)

        # modify the property class
        property_class.addLabel('en', "This is english comment")
        property_class.rmLabel('de')
        property_class.addComment('it', "Commentario italiano")
        self.last_modification_date, property_class_updated = property_class.update(
            self.last_modification_date)
        self.onto.lastModificationDate = self.last_modification_date
        self.assertEqual(property_class_updated.label['en'],
                         "This is english comment")
        self.assertEqual(property_class_updated.comment['it'],
                         "Commentario italiano")

        # delete the resource class to clean up
        self.last_modification_date = property_class_updated.delete(
            self.last_modification_date)
        self.onto.lastModificationDate = self.last_modification_date