Skip to content

Commit

Permalink
Merge pull request #30 from SvenSommer/feature/mapping-action-string
Browse files Browse the repository at this point in the history
Feature/mapping action string
  • Loading branch information
SvenSommer authored May 14, 2024
2 parents 304aa62 + 7c805f3 commit ea4fa3c
Show file tree
Hide file tree
Showing 24 changed files with 789 additions and 32 deletions.
17 changes: 10 additions & 7 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,31 @@
"name": "Generate eRP",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/main.py",
"program": "main.py",
"console": "integratedTerminal",
"justMyCode": true,
"args": [
"--project-dir",
"projects/erp",
"../../projects/erp",
"--html",
"--json"
]
],
"cwd": "${workspaceFolder}/service/src",
},
{
"name": "Generate ApoVZD",
"type": "debugpy",
"request": "launch",
"program": "${workspaceFolder}/main.py",
"program": "main.py",
"console": "integratedTerminal",
"justMyCode": true,
"args": [
"--project-dir",
"projects/apovzd",
"../../projects/apovzd",
"--html",
"--json"
]
],
"cwd": "${workspaceFolder}/service/src",
},
{
"name": "Flask App eRP",
Expand All @@ -39,8 +41,9 @@
"program": "server.py",
"args": [
"--project-dir",
"projects/erp"
"../../projects/erp"
],
"cwd": "${workspaceFolder}/service/src",
"jinja": true,
"justMyCode": true
},
Expand Down
6 changes: 0 additions & 6 deletions requirements.txt

This file was deleted.

73 changes: 73 additions & 0 deletions rest/requests.http
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ GET http://{{host}}/spec

###

# @name getclassifications
GET http://{{host}}/classification

###

# @name getmappings
GET http://{{host}}/mappings

Expand Down Expand Up @@ -73,3 +78,71 @@ Content-Type: application/json
{
"fixed": "{{fixed}}"
}

###

# @name post_copy_from
POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "copy_from",
"target": "{{targetdiff}}"
}

###


# @name post_copy_to
POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "copy_to",
"target": "{{targetdiff}}"
}

###

# @name post_fixed

POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "fixed",
"value": "fixed-value"
}

###

# @name post_use

POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "use"
}

###

# @name post_not_use

POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "not_use"
}

###

# @name post_empty

POST http://{{host}}/mapping/{{mapping_id}}/field/{{field_id}}/action
Content-Type: application/json

{
"action": "empty"
}
15 changes: 15 additions & 0 deletions service/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Structure Comparer Service

## Develop

Install with

```bash
pip install --editable .
```

Run all tests with

```bash
pytest
```
360 changes: 360 additions & 0 deletions service/poetry.lock

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions service/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[tool.poetry]
name = "structure-comparer"
version = "0.1.0"
description = ""
authors = ["Alexander Essenwanger <a.essenwanger@gematik.de>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.12"
jinja2 = "^3.1.4"
flask = ">=3.0,<4.0"
flask-swagger = ">=0.2.14,<0.3.0"
flask-cors = "^4.0.1"
pyyaml = "^6.0.1"


[tool.poetry.group.dev.dependencies]
black = "^24.4.2"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
File renamed without changes.
File renamed without changes.
96 changes: 95 additions & 1 deletion server.py → service/src/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@


from structure_comparer.serve import (
get_classifications_int,
get_mapping_fields_int,
get_mapping_int,
get_mappings_int,
init_project,
post_mapping_field_int,
post_mapping_classification_int,
)


Expand All @@ -19,7 +21,6 @@ def create_app(project_dir: Path):
app = Flask(__name__)
CORS(app, origins="http://localhost:4200")


# project config
project = init_project(project_dir)
setattr(app, "project", project)
Expand All @@ -28,6 +29,26 @@ def create_app(project_dir: Path):
def hello_world():
return "<p>Hello, World!</p>"

@app.route("/classification", methods=["GET"])
def get_classifications():
"""
Get all classifications
---
produces:
- application/json
responses:
200:
description: Classifications
schema:
required:
- classifications
properties:
classifications:
type: array
items: string
"""
return get_classifications_int()

@app.route("/mappings", methods=["GET"])
def get_mappings():
"""
Expand Down Expand Up @@ -101,6 +122,10 @@ def get_mapping(id: str):
type: string
classification:
type: string
classifications_allowed
type: array
items:
string
extension:
type: string
extra:
Expand Down Expand Up @@ -252,6 +277,75 @@ def post_mapping_field(mapping_id: str, field_id: str):

return "", 200

@app.route(
"/mapping/<mapping_id>/field/<field_id>/classification", methods=["POST"]
)
def post_mapping_classification(mapping_id: str, field_id: str):
"""
Post a manual classification for a field
Overrides the default action of a field. `action` that should set for the field, `target` is the target of copy action and `value` may be a fixed value.
---
consumes:
- application/json
parameters:
- in: path
name: mapping_id
type: string
required: true
description: The id of the mapping
- in: path
name: field_id
type: string
required: true
description: The id of the field
- in: body
name: body
schema:
required:
- action
properties:
action:
type: string
enum:
- copy_from
- copy_to
- fixed
- use
- not_use
- empty
description: Which action should be performed
target:
type: string
description: Field that is targetted (for copy actions)
value:
type: string
description: The fixed value
responses:
200:
description: The field was updated
400:
description: There was something wrong with the request
schema:
properties:
error:
type: string
description: An error message
404:
description: Mapping or field not found
"""
try:
result = post_mapping_classification_int(
app.project, mapping_id, field_id, request.get_json()
)
except ValueError as e:
error = {"error": str(e)}
return jsonify(error), 400
else:
if result is None:
return "", 404

return "", 200

@app.route("/spec", methods=["GET"])
def spec():
swag = swagger(app)
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ def compare_profile(profile_map: ProfileMap) -> Comparison:
classifications and remarks.
"""

# Iterate over all mappings (each entry are mapping to the same profile)
comparison = generate_comparison(profile_map)
fill_classification_remark(comparison)

return comparison


def generate_comparison(profile_map: ProfileMap) -> Comparison:
# Iterate over all mappings (each entry are mapping to the same profile)
comparison = Comparison()

Expand Down Expand Up @@ -112,11 +120,42 @@ def compare_profile(profile_map: ProfileMap) -> Comparison:

# Add remarks and classifications for each field
for field in comparison.fields.values():
_classify_remark_field(field, source_profiles, target_profile, comparison)
_fill_allowed_classifications(field, source_profiles, target_profile)

return comparison


def fill_classification_remark(comparison: Comparison):
for field in comparison.fields.values():
_classify_remark_field(
field, comparison.source_profiles, comparison.target_profile, comparison
)


def _fill_allowed_classifications(
field: ComparisonField, source_profiles: List[str], target_profile: str
):
allowed = set([c for c in Classification])

any_source_present = any(
[field.profiles[profile].present for profile in source_profiles]
)
target_present = field.profiles[target_profile].present

if not any_source_present:
allowed -= set(
[Classification.USE, Classification.NOT_USE, Classification.COPY_TO]
)
else:
allowed -= set([Classification.EMPTY])
if not target_present:
allowed -= set(
[Classification.USE, Classification.EMPTY, Classification.COPY_FROM]
)

field.classifications_allowed = list(allowed)


def _classify_remark_field(
field: ComparisonField,
source_profiles: List[str],
Expand Down
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit ea4fa3c

Please sign in to comment.