Ejemplo n.º 1
0
def overview(subgraph_id):
    user_id = g.user['id']

    db = get_db()

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    subgraph = db.execute('SELECT * FROM subgraph WHERE id = ?',
                          (subgraph_id, )).fetchone()

    if subgraph is None:
        message = '{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id)
        return redirect(url_for('tool.index', message=quote(message)))

    if not subgraph_access(user_id, subgraph_id) and not subgraph['finished']:
        message = 'You have no access to {} with id {}.'.format(
            current_app.config['FRONTEND_CONFIG']['subgraph_term'],
            subgraph_id)
        return redirect(url_for('tool.index', message=quote(message)))

    return render_template(
        'tool/overview.html',
        subgraph=subgraph,
        rdf_graph=get_subgraph_knowledge(subgraph_id).get_graph(clean=True,
                                                                ontology=True))
Ejemplo n.º 2
0
def read_only_view(subgraph_id):
    """Edit view.
    Displays knowledge about a subgraph and allows users to edit it."""
    db = get_db()

    subgraph = db.execute('SELECT * FROM subgraph WHERE id = ?',
                          (subgraph_id, )).fetchone()

    if subgraph is None:
        message = '{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id)
        # for some reason I need to unquote two times (once via url_for, once via quote) on the server, else
        # I'd get a bad request
        return redirect(url_for('tool.index', message=quote(message)))

    if not subgraph['finished']:
        message = 'You have no access to {} with id {}.'.format(
            current_app.config['FRONTEND_CONFIG']['subgraph_term'],
            subgraph_id)
        return redirect(url_for('tool.index', message=quote(message)))

    root = get_subgraph_knowledge(subgraph_id).get_root()

    return render_template('tool/edit.html',
                           subgraph=subgraph,
                           root=root,
                           read_only=True)
Ejemplo n.º 3
0
def undo_delete_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    # TODO actually we should check whether restoring the information would violate any
    #  functional property constraints, but that would be very complicated and currently we
    #  have no described functional deletable entities where that could happen

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    subgraph_knowledge.undo_delete_individual(entity_uri)

    return jsonify()
Ejemplo n.º 4
0
def get_overview():
    subgraph_id = request.json.get('subgraph_id')

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    db = get_db()
    subgraph = db.execute('SELECT * FROM subgraph WHERE id = ?',
                          (subgraph_id, )).fetchone()

    if subgraph is None:
        return jsonify(error='{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id))

    if not subgraph['finished']:
        return jsonify(error='You have no access to {} with id {}.'.format(
            current_app.config['FRONTEND_CONFIG']['subgraph_term'],
            subgraph_id))

    render_overview_table = get_template_attribute('tool/overview_table.html',
                                                   'overview')
    overview_table = render_overview_table(
        get_subgraph_knowledge(subgraph_id).get_graph(clean=True,
                                                      ontology=True))

    return jsonify(overview_table=overview_table)
Ejemplo n.º 5
0
def delete_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if not subgraph_knowledge.is_individual_deletable(entity_uri):
        return jsonify(error='You are not allowed to delete this entity.')

    deleted = subgraph_knowledge.delete_individual_recursive(entity_uri)

    if property_uri:
        is_functional = get_ontology().is_property_functional(property_uri)
        return jsonify(deleted=deleted, functional=is_functional)

    return jsonify(deleted=deleted)
Ejemplo n.º 6
0
def change_label():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    label = request.json.get('label')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')
    if not label or label.isspace():
        return jsonify(error='Label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if not subgraph_knowledge.is_individual_deletable(entity_uri):
        return jsonify(
            error='You are not allowed to change the label of this entity.')

    subgraph_knowledge.change_label(entity_uri, label.strip())

    return jsonify()
Ejemplo n.º 7
0
def add_subgraph():
    """Add a new subgraph.

    Request args:
        name (str): Name of the new subgraph.

    Context:
        g.user (sqlite3.Row): Logged in user. The new subgraph will be made accessible to this user.

    Returns JSON:
        redirect (str): URL of the new subgraph.
        error (str): An error message if something went wrong.

    """
    user_id = g.user['id']
    subgraph_name = request.json.get('name')

    if not subgraph_name or subgraph_name.isspace():
        return jsonify(error='{} name cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    db = get_db()
    db_cursor = db.cursor()

    db_cursor.execute(
        'INSERT INTO subgraph (name, finished, deleted) VALUES (?, ?, ?)',
        (subgraph_name, False, False))

    subgraph_id = db_cursor.lastrowid

    db.execute('INSERT INTO access (user_id, subgraph_id) VALUES (?, ?)',
               (user_id, subgraph_id))

    get_subgraph_knowledge(subgraph_id).execute_ratio_instructions(
        get_new_subgraph_instructions())

    db.commit()
    return jsonify(redirect=url_for('tool.edit_view', subgraph_id=subgraph_id))
Ejemplo n.º 8
0
def change_value():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')
    index = request.json.get('index')
    value = request.json.get('value').strip()

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if index is None:
        return jsonify(error='Index cannot be empty.')
    try:
        index = int(index)
    except ValueError:
        return jsonify(error='Index has to be an integer.')
    if value is None:
        return jsonify(error='Value cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if get_ontology().is_property_described(property_uri):
        return jsonify(
            error=
            'You have to use /_change_label to change the label of a described individual'
        )

    if index == subgraph_knowledge.get_property_free_index(
            entity_uri, property_uri):
        subgraph_knowledge.new_value(entity_uri, property_uri)
    validity = subgraph_knowledge.change_value(entity_uri, property_uri, index,
                                               value.strip())
    if validity:
        return jsonify(validity=validity)

    return jsonify()
Ejemplo n.º 9
0
def add_value():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    property_uri = request.json.get('property_uri')
    entity_uri = request.json.get('entity_uri')

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not entity_uri or property_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    field = subgraph_knowledge.get_field(entity_uri, property_uri)

    if field.is_described:
        return jsonify(
            error='You have to use {} to add a described individual'.format(
                url_for('knowledge.add_entity')))
    if field.is_functional and field.values:
        return jsonify(
            error='You cannot add more than one value to this field.')

    index = subgraph_knowledge.new_value(entity_uri, property_uri)

    if field.options is None:
        render_value_div = get_template_attribute('tool/edit_macros.html',
                                                  'value_free')
    else:
        render_value_div = get_template_attribute('tool/edit_macros.html',
                                                  'value_options')
    value_div = render_value_div(field, '', index)

    return jsonify(value_div=value_div)
Ejemplo n.º 10
0
def download_rdf(subgraph_id):
    user_id = g.user['id']

    if not subgraph_id:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id, user_id))

    filename = '{}_{}_{}.ttl'.format(
        current_app.config['FRONTEND_CONFIG']['Subgraph_term'], subgraph_id,
        strftime('%Y-%m-%d-%H-%M-%S'))
    content = get_subgraph_knowledge(subgraph_id).get_serialization(clean=True)

    return Response(
        content,
        mimetype='text/plain',
        headers={'Content-disposition': 'attachment; filename=' + filename})
Ejemplo n.º 11
0
def search():
    filter_data = request.json

    # todo get_result(filter_data) should be a method of the filter
    # get list of subgraphs that are finished and not deleted
    db = get_db()
    rows = db.execute('SELECT id FROM access JOIN subgraph ON subgraph_id = id'
                      ' WHERE deleted = 0 AND finished = 1').fetchall()
    results = {row['id'] for row in rows}
    knowledge = {
        subgraph_id:
        {(str(p), str(o))
         for s, p, o in get_subgraph_knowledge(subgraph_id).get_graph(
             clean=True)}
        for subgraph_id in results
    }
    results = filter(
        lambda subgraph_id: all(po in knowledge[subgraph_id]
                                for po in filter_data.items()), results)

    return jsonify(results=[str(subgraph_id) for subgraph_id in results])
Ejemplo n.º 12
0
def add_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    property_uri = request.json.get('property_uri')
    parent_uri = request.json.get('entity_uri')
    entity_label = request.json.get('label')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not parent_uri or parent_uri.isspace():
        return jsonify(error='Parent URI cannot be empty.')
    if not entity_label or entity_label.isspace():
        return jsonify(error='Entity label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    ontology = get_ontology()
    field_is_deletable = ontology.is_property_deletable(property_uri)
    field_is_functional = ontology.is_property_functional(property_uri)
    field_values = subgraph_knowledge.get_property_values(
        parent_uri, property_uri)
    field_range = ontology.get_property_range(property_uri)

    if not field_is_deletable:
        return jsonify(
            error='You are not allowed to add entities to this field.')

    if field_is_functional and field_values:
        return jsonify(
            error='You cannot add more than one value to this field.')

    index = subgraph_knowledge.new_value(parent_uri, property_uri)
    entity, option_fields = subgraph_knowledge.new_individual(
        field_range, entity_label, True)
    subgraph_knowledge.change_value(parent_uri, property_uri, index,
                                    entity.uri)

    render_entity_div = get_template_attribute('tool/edit_macros.html',
                                               'entity_div')
    entity_div = render_entity_div(entity,
                                   index=index,
                                   is_deletable=field_is_deletable,
                                   collapsed=False)

    if option_fields:
        option_fields = [str(f.property_uri) for f in option_fields]
        render_option_div = get_template_attribute('tool/edit_macros.html',
                                                   'option_div')
        option_div = render_option_div(entity, True)
        return jsonify(entity_div=entity_div,
                       remove_plus=field_is_functional,
                       option_fields=option_fields,
                       option_div=option_div)

    return jsonify(entity_div=entity_div, remove_plus=field_is_functional)
Ejemplo n.º 13
0
def add_option():
    # If an index is given, the corresponding value is changed to the new option
    user_id = g.user['id']
    user_uri = g.user['uri']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')
    label = request.json.get('label')
    index = request.json.get('index')

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not label or label.isspace():
        return jsonify(error='Label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    ontology = get_ontology()

    if ontology.is_property_described(property_uri):
        return jsonify(
            error='Use _add_entity to add entities to a described field.')
    if not ontology.is_property_add_custom_option_allowed(property_uri):
        return jsonify(error='Adding options to this field is not allowed.')

    option, option_fields = ontology.new_option(
        ontology.get_property_range(property_uri), label, user_uri)

    if index is not None:
        try:
            index = int(index)
        except ValueError:
            return jsonify(error='Index has to be an integer.')
        # not only add the option to the ontology but also to the list of values of the field
        if not entity_uri or entity_uri.isspace():
            return jsonify(error='Entity URI cannot be empty.')

        if index == subgraph_knowledge.get_property_free_index(
                entity_uri, property_uri):
            index = subgraph_knowledge.new_value(entity_uri, property_uri)
        subgraph_knowledge.change_value(entity_uri, property_uri, index,
                                        option.uri)

    render_option_div = get_template_attribute('tool/edit_macros.html',
                                               'option_div')
    option_div = render_option_div(option, True)

    return jsonify(option_div=option_div,
                   option_fields=list(option_fields),
                   option_label=option.label,
                   option_uri=option.uri,
                   index=index)