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'
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)
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
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
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)
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)
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'
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"
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()
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)
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)
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"
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,)
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, )
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)
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)