예제 #1
0
def test_association():
    association1 = Association(identifier='test-association1',
                               src_topic_ref='test-topic1',
                               dest_topic_ref='test-topic2')

    # Instantiate and open topic store.
    store = TopicStore(username, password)
    store.open()

    # Persist association to store.
    if not store.topic_exists(TOPIC_MAP_IDENTIFIER, 'test-association1'):
        store.set_association(TOPIC_MAP_IDENTIFIER, association1)

    # Retrieve occurrence from store.
    association2 = store.get_association(TOPIC_MAP_IDENTIFIER, 'test-association1',
                                         resolve_attributes=RetrievalOption.RESOLVE_ATTRIBUTES)

    store.close()

    assert association2.identifier == 'test-association1'
    assert association2.instance_of == 'association'
    assert association2.scope == '*'  # Universal scope.
    assert len(association2.base_names) == 1
    assert association2.first_base_name.name == 'Undefined'
    assert association2.first_base_name.language is Language.ENG
    assert len(association2.attributes) == 1
    assert len(association2.occurrences) == 0
    assert len(association2.members) == 2
    assert association2.members[0].role_spec == 'related'
    assert association2.members[1].role_spec == 'related'
예제 #2
0
    def set_character(self, topic_map_identifier, character, scene_identifier):
        topic = Topic(character.identifier, character.instance_of,
                      character.name)
        self.topic_store.set_topic(topic_map_identifier, topic)

        description_attribute = Attribute(
            'description', character.description,
            topic.identifier) if character.description else None
        location_attribute = Attribute('location', character.location,
                                       topic.identifier)
        rotation_attribute = Attribute('rotation', character.rotation,
                                       topic.identifier)
        scale_attribute = Attribute('scale', character.scale, topic.identifier)

        attributes = [
            x for x in [
                description_attribute, location_attribute, rotation_attribute,
                scale_attribute
            ] if x is not None
        ]
        self.topic_store.set_attributes(topic_map_identifier, attributes)

        for asset in character.assets:
            occurrence = Occurrence(instance_of=asset.instance_of,
                                    topic_identifier=topic.identifier,
                                    resource_ref=asset.reference,
                                    resource_data=asset.data)
            self.topic_store.set_occurrence(topic_map_identifier, occurrence)

        scene_association = Association(
            instance_of='character',
            src_topic_ref=topic.identifier,  # The character's reference.
            dest_topic_ref=scene_identifier,
            src_role_spec='included-in',
            dest_role_spec='includes')
        self.topic_store.set_association(topic_map_identifier,
                                         scene_association)

        book_association = Association(
            instance_of='character',
            src_topic_ref=topic.identifier,  # The character's reference.
            dest_topic_ref='genesis',
            src_role_spec='included-in',
            dest_role_spec='includes',
            scope='book')
        self.topic_store.set_association(topic_map_identifier,
                                         book_association)
예제 #3
0
def create_association(map_identifier):
    topic_store = get_topic_store()

    topic_map = topic_store.get_topic_map(map_identifier, current_user.id)
    if topic_map is None:
        return jsonify({"status": "error", "code": 404}), 404

    if request.method == "POST":
        association_dest_topic_ref = request.form[
            "association-dest-topic-ref"].strip()
        association_dest_role_spec = request.form[
            "association-dest-role-spec"].strip()
        association_src_topic_ref = request.form[
            "association-src-topic-ref"].strip()
        association_src_role_spec = request.form[
            "association-src-role-spec"].strip()
        association_instance_of = request.form[
            "association-instance-of"].strip()
        association_scope = request.form["association-scope"].strip()
        association_name = request.form["association-name"].strip()
        association_identifier = request.form["association-identifier"].strip()

        if not topic_store.topic_exists(topic_map.identifier,
                                        association_dest_topic_ref):
            return jsonify({"status": "error", "code": 409}), 409
        if not topic_store.topic_exists(topic_map.identifier,
                                        association_src_topic_ref):
            return jsonify({"status": "error", "code": 409}), 409

        # If no values have been provided set their default values
        if not association_dest_role_spec:
            association_dest_role_spec = "related"
        if not association_src_role_spec:
            association_src_role_spec = "related"
        if not association_instance_of:
            association_instance_of = "association"
        if not association_scope:
            association_scope = UNIVERSAL_SCOPE
        if not association_name:
            association_name = "Undefined"
        if not association_identifier:
            association_identifier = ""

        association = Association(
            identifier=association_identifier,
            instance_of=association_instance_of,
            name=association_name,
            scope=association_scope,
            src_topic_ref=association_src_topic_ref,
            dest_topic_ref=association_dest_topic_ref,
            src_role_spec=association_src_role_spec,
            dest_role_spec=association_dest_role_spec,
        )

        # Persist association object to the topic store
        topic_store.set_association(map_identifier, association)

    return jsonify({"status": "success", "code": 201}), 201
예제 #4
0
def test_init_association1():
    association1 = Association()

    assert association1.instance_of == "association"
    assert association1.scope == "*"  # Universal Scope.
    assert len(association1.base_names) == 1
    assert association1.first_base_name.name == "Undefined"
    assert association1.first_base_name.language is Language.ENG
    assert len(association1.attributes) == 0
    assert len(association1.occurrences) == 0
    assert len(association1.members) == 0
예제 #5
0
 def set_temporal_connection(self, map_identifier: int,
                             source_identifier: str,
                             destination_identifier: str) -> None:
     association = Association(
         instance_of="temporal-navigation",
         src_topic_ref=source_identifier,
         dest_topic_ref=destination_identifier,
         src_role_spec="cause",
         dest_role_spec="effect",
     )
     self.topic_store.set_association(map_identifier, association)
예제 #6
0
 def set_navigation(self,
                    topic_map_identifier,
                    src_scene_identifier,
                    dest_scene_identifier,
                    src_scene_role='previous',
                    dest_scene_role='next'):
     association = Association(instance_of='navigation',
                               src_topic_ref=src_scene_identifier,
                               dest_topic_ref=dest_scene_identifier,
                               src_role_spec=src_scene_role,
                               dest_role_spec=dest_scene_role)
     self.topic_store.set_association(topic_map_identifier, association)
예제 #7
0
def test_init_association2():
    association2 = Association(instance_of='test',
                               scope='test-scope',
                               src_topic_ref='test-topic1',
                               dest_topic_ref='test-topic2')

    assert association2.instance_of == 'test'
    assert association2.scope == 'test-scope'
    assert len(association2.base_names) == 1
    assert association2.first_base_name.name == 'Undefined'
    assert association2.first_base_name.language is Language.ENG
    assert len(association2.attributes) == 0
    assert len(association2.occurrences) == 0
    assert len(association2.members) == 2
    assert association2.members[0].role_spec == 'related'
    assert association2.members[1].role_spec == 'related'
예제 #8
0
def test_init_association2():
    association2 = Association(
        instance_of="test",
        scope="test-scope",
        src_topic_ref="test-topic1",
        dest_topic_ref="test-topic2",
    )

    assert association2.instance_of == "test"
    assert association2.scope == "test-scope"
    assert len(association2.base_names) == 1
    assert association2.first_base_name.name == "Undefined"
    assert association2.first_base_name.language is Language.ENG
    assert len(association2.attributes) == 0
    assert len(association2.occurrences) == 0
    assert len(association2.members) == 2
    assert association2.members[0].role_spec == "related"
    assert association2.members[1].role_spec == "related"
예제 #9
0
def store_association(
    store,
    topic_map_identifier,
    src_topic_ref,
    src_role_spec,
    dest_topic_ref,
    dest_role_spec,
    instance_of="navigation",
):
    store.open()
    association = Association(
        instance_of=instance_of,
        scope=UNIVERSAL_SCOPE,
        src_topic_ref=src_topic_ref,
        dest_topic_ref=dest_topic_ref,
        src_role_spec=src_role_spec,
        dest_role_spec=dest_role_spec,
    )
    # Persist object to the topic store
    store.set_association(topic_map_identifier, association)
    store.close()
예제 #10
0
    def set_scene(self, topic_map_identifier, scene):
        topic = Topic(scene.identifier, scene.instance_of, scene.name)
        self.topic_store.set_topic(topic_map_identifier, topic)

        description_attribute = Attribute(
            'description', scene.description,
            topic.identifier) if scene.description else None
        location_attribute = Attribute('location', scene.location,
                                       topic.identifier)
        rotation_attribute = Attribute('rotation', scene.rotation,
                                       topic.identifier)
        scale_attribute = Attribute('scale', scene.scale, topic.identifier)
        ordinal_attribute = Attribute(
            'ordinal', scene.ordinal,
            topic.identifier) if scene.ordinal else None

        attributes = [
            x for x in [
                description_attribute, location_attribute, rotation_attribute,
                scale_attribute, ordinal_attribute
            ] if x is not None
        ]
        self.topic_store.set_attributes(topic_map_identifier, attributes)

        for asset in scene.assets:
            occurrence = Occurrence(instance_of=asset.instance_of,
                                    topic_identifier=topic.identifier,
                                    resource_ref=asset.reference,
                                    resource_data=asset.data)
            self.topic_store.set_occurrence(topic_map_identifier, occurrence)

        book_association = Association(
            instance_of='scene',
            src_topic_ref=topic.identifier,  # The scene's reference.
            dest_topic_ref='genesis',
            src_role_spec='included-in',
            dest_role_spec='includes',
            scope='book')
        self.topic_store.set_association(topic_map_identifier,
                                         book_association)
예제 #11
0
 def set_spatial_connection(
     self,
     map_identifier: int,
     source_identifier: str,
     destination_identifier: str,
     navigation_identifier: str,
 ) -> None:
     association = Association(
         instance_of="spatial-navigation",
         src_topic_ref=source_identifier,
         dest_topic_ref=destination_identifier,
         src_role_spec="from",
         dest_role_spec="to",
     )
     attribute = Attribute(
         "navigation-identifier",
         navigation_identifier,
         association.identifier,
         data_type=DataType.STRING,
     )
     self.topic_store.set_association(map_identifier, association)
     self.topic_store.set_attribute(map_identifier, attribute)
예제 #12
0
def test_association():
    association1 = Association(
        identifier="test-association1",
        src_topic_ref="test-topic1",
        dest_topic_ref="test-topic2",
    )

    # Instantiate and open topic store.
    with TopicStore(database_username, database_password,
                    dbname=database_name) as store:

        # Associations are topics, as well (in TopicDB). For that reason, to check for the existence of an
        # association we can use the *topic_exists* method.
        if not store.topic_exists(TOPIC_MAP_IDENTIFIER, "test-association1"):
            store.set_association(
                TOPIC_MAP_IDENTIFIER,
                association1)  # Persist association to store.

        # Retrieve occurrence from store.
        association2 = store.get_association(
            TOPIC_MAP_IDENTIFIER,
            "test-association1",
            resolve_attributes=RetrievalMode.RESOLVE_ATTRIBUTES,
        )

    assert association2.identifier == "test-association1"
    assert association2.instance_of == "association"
    assert association2.scope == "*"  # Universal scope.
    assert len(association2.base_names) == 1
    assert association2.first_base_name.name == "Undefined"
    assert association2.first_base_name.language is Language.ENG
    assert len(association2.attributes) == 1
    assert len(association2.occurrences) == 0
    assert len(association2.members) == 2
    assert association2.members[0].role_spec == "related"
    assert association2.members[1].role_spec == "related"
예제 #13
0
def create(map_identifier, topic_identifier):
    topic_store = get_topic_store()

    topic_map = topic_store.get_topic_map(map_identifier, current_user.id)
    if topic_map is None:
        abort(404)
    # If the map doesn't belong to the user and they don't have the right
    # collaboration mode on the map, then abort
    if not topic_map.owner and topic_map.collaboration_mode is not CollaborationMode.EDIT:
        abort(403)

    topic = topic_store.get_topic(
        map_identifier, topic_identifier, resolve_attributes=RetrievalMode.RESOLVE_ATTRIBUTES,
    )
    if topic is None:
        abort(404)

    error = 0

    if request.method == "POST":
        form_association_dest_topic_ref = request.form["association-dest-topic-ref"].strip()
        form_association_dest_role_spec = request.form["association-dest-role-spec"].strip()
        form_association_src_topic_ref = topic_identifier
        form_association_src_role_spec = request.form["association-src-role-spec"].strip()
        form_association_instance_of = request.form["association-instance-of"].strip()
        form_association_scope = request.form["association-scope"].strip()
        form_association_name = request.form["association-name"].strip()
        form_association_identifier = request.form["association-identifier"].strip()

        # If no values have been provided set their default values
        if not form_association_dest_role_spec:
            form_association_dest_role_spec = "related"
        if not form_association_src_role_spec:
            form_association_src_role_spec = "related"
        if not form_association_instance_of:
            form_association_instance_of = "association"
        if not form_association_scope:
            form_association_scope = session["current_scope"]
        if not form_association_name:
            form_association_name = "Undefined"

        # Validate form inputs
        if not topic_store.topic_exists(topic_map.identifier, form_association_dest_topic_ref):
            error = error | 1
        if form_association_dest_role_spec != "related" and not topic_store.topic_exists(
            topic_map.identifier, form_association_dest_role_spec
        ):
            error = error | 2
        if form_association_src_role_spec != "related" and not topic_store.topic_exists(
            topic_map.identifier, form_association_src_role_spec
        ):
            error = error | 4
        if form_association_instance_of != "association" and not topic_store.topic_exists(
            topic_map.identifier, form_association_instance_of
        ):
            error = error | 8
        if form_association_scope != UNIVERSAL_SCOPE and not topic_store.topic_exists(
            topic_map.identifier, form_association_scope
        ):
            error = error | 16
        if form_association_identifier and topic_store.topic_exists(topic_map.identifier, form_association_identifier):
            error = error | 32

        # If role identifier topics are missing then create them
        if error & 2:  # Destination role spec
            pass
        if error & 4:  # Source role spec
            pass

        if error != 0:
            flash(
                "An error occurred when submitting the form. Please review the warnings and fix accordingly.",
                "warning",
            )
        else:
            association = Association(
                identifier=form_association_identifier,
                instance_of=form_association_instance_of,
                name=form_association_name,
                scope=form_association_scope,
                src_topic_ref=form_association_src_topic_ref,
                dest_topic_ref=form_association_dest_topic_ref,
                src_role_spec=form_association_src_role_spec,
                dest_role_spec=form_association_dest_role_spec,
            )

            # Persist association object to the topic store
            topic_store.set_association(map_identifier, association)

            flash("Association successfully created.", "success")
            return redirect(
                url_for("association.index", map_identifier=topic_map.identifier, topic_identifier=topic_identifier,)
            )

        return render_template(
            "association/create.html",
            error=error,
            topic_map=topic_map,
            topic=topic,
            association_instance_of=form_association_instance_of,
            association_src_topic_ref=form_association_src_topic_ref,
            association_src_role_spec=form_association_src_role_spec,
            association_dest_topic_ref=form_association_dest_topic_ref,
            association_dest_role_spec=form_association_dest_role_spec,
            association_scope=form_association_scope,
            association_name=form_association_name,
            association_identifier=form_association_identifier,
        )

    return render_template("association/create.html", error=error, topic_map=topic_map, topic=topic,)
예제 #14
0
def create(map_identifier, topic_identifier):
    topic_store = get_topic_store()

    topic_map = topic_store.get_map(map_identifier, current_user.id)
    if topic_map is None:
        abort(404)
    # If the map doesn't belong to the user and they don't have the right
    # collaboration mode on the map, then abort
    if not topic_map.owner and topic_map.collaboration_mode is not CollaborationMode.EDIT:
        abort(403)

    topic = topic_store.get_topic(
        map_identifier,
        topic_identifier,
        resolve_attributes=RetrievalMode.RESOLVE_ATTRIBUTES,
    )
    if topic is None:
        abort(404)

    map_notes_count = topic_store.get_topic_occurrences_statistics(
        map_identifier, "notes")["note"]
    error = 0

    flash(
        "Take a look at this page to see practical examples of <a href='https://brettkromkamp.com/posts/semantically-meaningful-relationships/'>semantically meaningful relationships</a>.",
        "info",
    )

    if request.method == "POST":
        form_association_dest_topic_ref = request.form[
            "association-dest-topic-ref"].strip()
        form_association_dest_role_spec = request.form[
            "association-dest-role-spec"].strip()
        form_association_src_topic_ref = topic_identifier
        form_association_src_role_spec = request.form[
            "association-src-role-spec"].strip()
        form_association_instance_of = request.form[
            "association-instance-of"].strip()
        form_association_scope = request.form["association-scope"].strip()
        form_association_name = request.form["association-name"].strip()
        form_association_identifier = request.form[
            "association-identifier"].strip()

        # If no values have been provided set their default values
        if not form_association_dest_role_spec:
            form_association_dest_role_spec = "related"
        if not form_association_src_role_spec:
            form_association_src_role_spec = "related"
        if not form_association_instance_of:
            form_association_instance_of = "association"
        if not form_association_scope:
            form_association_scope = session["current_scope"]
        if not form_association_name:
            form_association_name = "Undefined"
        if not form_association_identifier:
            form_association_identifier = ""

        # Validate form inputs
        if not topic_store.topic_exists(topic_map.identifier,
                                        form_association_dest_topic_ref):
            error = error | 1
        if form_association_dest_role_spec != "related" and not topic_store.topic_exists(
                topic_map.identifier, form_association_dest_role_spec):
            error = error | 2
        if form_association_src_role_spec != "related" and not topic_store.topic_exists(
                topic_map.identifier, form_association_src_role_spec):
            error = error | 4
        if form_association_instance_of != "association" and not topic_store.topic_exists(
                topic_map.identifier, form_association_instance_of):
            error = error | 8
        if form_association_scope != UNIVERSAL_SCOPE and not topic_store.topic_exists(
                topic_map.identifier, form_association_scope):
            error = error | 16
        if form_association_identifier and topic_store.topic_exists(
                topic_map.identifier, form_association_identifier):
            error = error | 32

        # TODO: Flag an error to prevent the user from creating an association with the reserved
        # 'navigation' or 'categorization' types

        # If role identifier topics are missing then create them
        if error & 2:  # Destination role spec
            pass
        if error & 4:  # Source role spec
            pass

        if error != 0:
            flash(
                "An error occurred when submitting the form. Please review the warnings and fix accordingly.",
                "warning",
            )
        else:
            association = Association(
                identifier=form_association_identifier,
                instance_of=form_association_instance_of,
                name=form_association_name,
                scope=form_association_scope,
                src_topic_ref=form_association_src_topic_ref,
                src_role_spec=form_association_src_role_spec,
                dest_topic_ref=form_association_dest_topic_ref,
                dest_role_spec=form_association_dest_role_spec,
            )

            # Persist association object to the topic store
            topic_store.create_association(map_identifier, association)

            flash("Association successfully created.", "success")
            return redirect(
                url_for(
                    "association.index",
                    map_identifier=topic_map.identifier,
                    topic_identifier=topic_identifier,
                ))

        return render_template(
            "association/create.html",
            error=error,
            topic_map=topic_map,
            topic=topic,
            association_instance_of=form_association_instance_of,
            association_src_topic_ref=form_association_src_topic_ref,
            association_src_role_spec=form_association_src_role_spec,
            association_dest_topic_ref=form_association_dest_topic_ref,
            association_dest_role_spec=form_association_dest_role_spec,
            association_scope=form_association_scope,
            association_name=form_association_name,
            association_identifier=form_association_identifier,
            map_notes_count=map_notes_count,
        )

    return render_template(
        "association/create.html",
        error=error,
        topic_map=topic_map,
        topic=topic,
        map_notes_count=map_notes_count,
    )
예제 #15
0
    def set_entity(self,
                   map_identifier: int,
                   entity: Entity,
                   event_identifier: str = None) -> None:
        if (self.source_directory is None) or (self.destination_directory is
                                               None):
            raise StoryDbError("Missing resource directories")

        if not self.topic_store.topic_exists(map_identifier,
                                             entity.identifier):
            topic = Topic(entity.identifier, entity.instance_of, entity.name)
            timestamp = str(datetime.now())
            modification_attribute = Attribute(
                "modification-timestamp",
                timestamp,
                topic.identifier,
                data_type=DataType.TIMESTAMP,
            )
            self.topic_store.set_topic(map_identifier, topic)
            self.topic_store.set_attribute(map_identifier,
                                           modification_attribute)

            if hasattr(entity, "description") and entity.description:
                text_occurrence = Occurrence(
                    instance_of="text",
                    topic_identifier=entity.identifier,
                    resource_data=entity.description,
                )
                self.topic_store.set_occurrence(map_identifier,
                                                text_occurrence)
            if hasattr(entity, "animation") and entity.animation:
                entity.add_attribute(
                    Attribute(
                        "animation",
                        entity.animation,
                        entity.identifier,
                        data_type=DataType.STRING,
                    ))

            # Create the file directory for this topic map and topic if it doesn't already exist
            file_directory = os.path.join(self.destination_directory,
                                          str(map_identifier),
                                          entity.identifier)
            if not os.path.isdir(file_directory):
                os.makedirs(file_directory)

            for resource in entity.resources:
                occurrence = Occurrence(
                    instance_of=resource.instance_of,
                    topic_identifier=entity.identifier,
                    resource_ref=resource.reference,
                    resource_data=resource.data,
                )
                title_attribute = Attribute(
                    "title",
                    resource.title,
                    occurrence.identifier,
                    data_type=DataType.STRING,
                )
                self.topic_store.set_occurrence(map_identifier, occurrence)
                self.topic_store.set_attribute(map_identifier, title_attribute)

                # Copy resource file to appropriate (topic) directory
                if occurrence.resource_ref:
                    source_file_path = os.path.join(self.source_directory,
                                                    occurrence.resource_ref)
                    destination_file_path = os.path.join(
                        self.destination_directory,
                        str(map_identifier),
                        entity.identifier,
                        occurrence.resource_ref,
                    )
                    if not os.path.isfile(destination_file_path):
                        shutil.copy(source_file_path, destination_file_path)

            if hasattr(entity, "tags"):
                self.topic_store.set_tags(map_identifier, entity.identifier,
                                          entity.tags)

            self.topic_store.set_attributes(map_identifier, entity.attributes)

        if event_identifier:
            association = Association(
                instance_of=entity.instance_of,
                src_topic_ref=entity.identifier,
                dest_topic_ref=event_identifier,
                src_role_spec="included-in",
                dest_role_spec="includes",
            )
            self.topic_store.set_association(map_identifier, association)
예제 #16
0
    def set_event(self,
                  map_identifier: int,
                  event: Event,
                  parent_event: Event = None) -> None:
        if not self.topic_store.topic_exists(map_identifier, event.identifier):
            event.add_attribute(
                Attribute("rank",
                          str(event.rank),
                          event.identifier,
                          data_type=DataType.NUMBER))

            # What?
            event.add_attribute(
                Attribute(
                    "action-property",
                    event.action_property,
                    event.identifier,
                    data_type=DataType.STRING,
                ))
            # When?
            if event.when is None:
                timestamp = str(datetime.now())
                event.when = TimeInterval(timestamp, timestamp)
            event.add_attribute(
                Attribute(
                    "from-time-point",
                    event.when.from_time_point,
                    event.identifier,
                    data_type=DataType.TIMESTAMP,
                ))
            event.add_attribute(
                Attribute(
                    "to-time-point",
                    event.when.to_time_point,
                    event.identifier,
                    data_type=DataType.TIMESTAMP,
                ))

            self.set_entity(map_identifier, event)

            # What?
            if parent_event:
                association = Association(
                    instance_of="event",
                    src_topic_ref=event.identifier,
                    dest_topic_ref=parent_event.identifier,
                    src_role_spec="included-in",
                    dest_role_spec="includes",
                )
                self.topic_store.set_association(map_identifier, association)

            for key, value in event.events.items():
                self.set_event(map_identifier, value, event)  # Recursive call

            # Who?
            for key, value in event.participants.items():
                self.set_entity(map_identifier, value, event.identifier)
            for key, value in event.things.items():
                self.set_entity(map_identifier, value, event.identifier)

            # Where?
            if event.where:
                self.set_place(map_identifier, event.where, event.identifier)