Re: Safe manipulation of RDF data (from semantic-web)

Thank you very much for the help. I'll setup the system next and see how 
it works out.

Br,
Mikael


On 17/09/2019 14:57, Martynas Jusevičius wrote:
> Hi Mikael,
>
> the template URI on its own is irrelevant here, it could be a blank
> node resource. It becomes important when one intends to reuse
> templates, e.g. extend them or reference them, possibly from another
> LDT ontology.
>
> Yes it is the ldt:match that holds the URI template that request URI
> is matched against. I have expanded the explanation here:
> https://github.com/AtomGraph/Processor/wiki/Linked-Data-Templates#templates
>
> As for the agent ID, one option to pass a value to the LDT template is
> using template parameters:
> https://github.com/AtomGraph/Processor/wiki/Linked-Data-Templates#parameters
>
> Then if a request URI is
> https://resource.lingsoft.fi/286c384d-cd5c-4887-9b85-94c0c147f709?agent=123456,
> a variable binding (?agent, "123456") is applied to the query string
> from ldt:query, before it is executed.
> This might or might not work for your use case.
>
> Martynas
>
> On Tue, Sep 17, 2019 at 1:43 PM Mikael Pesonen
> <mikael.pesonen@lingsoft.fi> wrote:
>>
>> Hmm, still mixing up things. So ldt:match has to match the resource URI.
>>
>> On 17/09/2019 12:13, Mikael Pesonen wrote:
>>> Ok now I got it, the template address has to be the same as resource URI.
>>> Just one question, in our case, https://base/{uuid}, how should we
>>> forward the agent id (access level) to the template for utilizing ACL?
>>>
>>>
>>>
>>> On 17/09/2019 11:40, Martynas Jusevičius wrote:
>>>> Thanks Mikael,
>>>>
>>>> the example makes it clearer.
>>>>
>>>> So the URI template for all persons (and I guess all resources in
>>>> general?) is "/{uuid}", if we take https://resource.lingsoft.fi as the
>>>> base URI. Which means that you could not match two different LDT
>>>> templates for different types of persons.
>>>>
>>>> Then my suggestion with using a single template with a query that
>>>> references the ACL graph still stands. Let me know if you need help
>>>> setting it up in Processor.
>>>>
>>>> Martynas
>>>>
>>>> On Mon, Sep 16, 2019 at 11:27 AM Mikael Pesonen
>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>> Here is a sample data:
>>>>>
>>>>> <https://resource.lingsoft.fi/286c384d-cd5c-4887-9b85-94c0c147f709>
>>>>>            a                        foaf:Person ;
>>>>>            vcard:family-name        "Pesonen" ;
>>>>>            vcard:fn                 "Mikael Pesonen" ;
>>>>>            vcard:given-name         "Mikael" ;
>>>>>            vcard:hasEmail
>>>>> <https://resource.lingsoft.fi/cf9b02b7-bd0d-486e-b0d9-da1464e27d2e> ,
>>>>> <https://resource.lingsoft.fi/5c04aa23-6c42-44a1-9ac9-69ee255ac170> ;
>>>>>            vcard:hasGender          vcard:Male ;
>>>>>            vcard:hasInstantMessage
>>>>> <https://resource.lingsoft.fi/4aa01d37-744c-4964-a794-d997aa376584> ;
>>>>>            vcard:hasPhoto
>>>>> <https://resource.lingsoft.fi/8f4a4ddd-43c2-4e27-8ed7-996dd00e939c> ;
>>>>>            vcard:hasTelephone
>>>>> <https://resource.lingsoft.fi/3755ed0c-81b7-430e-92a0-16fc80ba41b4> ;
>>>>>            org:basedAt
>>>>> <https://resource.lingsoft.fi/b48a0820-6921-43fc-a346-e72397265bbe> ;
>>>>>            org:memberOf
>>>>> <https://resource.lingsoft.fi/810dfbff-e6fb-458a-b27d-3726a27e5109> ;
>>>>>            foaf:account
>>>>> <https://resource.lingsoft.fi/2f0aa772-f845-4f43-b607-dc65ff66b9aa> ;
>>>>> <https://resource.lingsoft.fi/cf9b02b7-bd0d-486e-b0d9-da1464e27d2e>
>>>>>            a                         vcard:Email , vcard:Work ;
>>>>>            rdfs:label                "***@lingsoft.fi" ;
>>>>>            vcard:hasValue <mailto:***@lingsoft.fi> .
>>>>>
>>>>>
>>>>> So most of the person's values are resources and every resource has id
>>>>> of type https://resource.lingsoft.fi/<UUID>.
>>>>>
>>>>>
>>>>> Mikael
>>>>>
>>>>>
>>>>> On 15/09/2019 01:02, Martynas Jusevičius wrote:
>>>>>> I meant the first and the ACL examples as alternatives, but yes you
>>>>>> can combine the approaches as well. Again, depends mostly on your URIs
>>>>>> - and are able to change their pattern?
>>>>>>
>>>>>> I think it would help if you could show some RDF data that represents
>>>>>> your case (does not have to be the actual person data :)) Either paste
>>>>>> inline or as a Gist if it's larger.
>>>>>>
>>>>>> Re. ACL, we use a filter in our LinkedDataHub platform that checks ACL
>>>>>> access before the actual LDT request is invoked. And if query results
>>>>>> need to depend on the access level, we reference the ACL dataset as I
>>>>>> showed in the example.
>>>>>>
>>>>>> Martynas
>>>>>>
>>>>>> On Fri, Sep 13, 2019 at 3:55 PM Mikael Pesonen
>>>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>>>> Looking at your first example, looks like that and this acl
>>>>>>> version work
>>>>>>> both?
>>>>>>>
>>>>>>> So as with your first example:
>>>>>>>
>>>>>>> /person/basic_access/{id}
>>>>>>> --
>>>>>>>
>>>>>>> :BasicPersonAccessItem a ldt:Template ;
>>>>>>>         ldt:match "/person/basic_access/{id}" ;
>>>>>>>         ldt:query :ConstructBasicPerson ;
>>>>>>>
>>>>>>> ----
>>>>>>> /person/admin_access/{id}
>>>>>>> --
>>>>>>> :AdminPersonAccessItem a ldt:Template ;
>>>>>>>         ldt:match "/person/admin_access/{id}" ;
>>>>>>>         ldt:query :ConstructFullPerson ;
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> And this acl example
>>>>>>>
>>>>>>> /person/{agent}/{id}
>>>>>>> --
>>>>>>> :PersonAccessItem a ldt:Template ;
>>>>>>>         ldt:match "/person/{agent}/{id}" ;
>>>>>>>         ldt:query :ConstructPerson ;
>>>>>>> ...
>>>>>>>
>>>>>>>
>>>>>>> ACL example sure is more refined since you can define the access
>>>>>>> levels
>>>>>>> in the ACL data.
>>>>>>>
>>>>>>>
>>>>>>> On 13/09/2019 16:25, Martynas Jusevičius wrote:
>>>>>>>> Well if you only have one kind of person resources with a single URI
>>>>>>>> pattern, then you cannot select (match) different LDT templates.
>>>>>>>> That is because an LDT template maps one URI pattern to one SPARQL
>>>>>>>> command. The matching process is not looking into the SPARQL query
>>>>>>>> results at all, only at the request URI and the application's LDT
>>>>>>>> ontology.
>>>>>>>>
>>>>>>>> I think you can solve this with a single query though. What we do is
>>>>>>>> provide the URI of the requesting agent as a query binding, e.g.
>>>>>>>> ?agent variable. Something like
>>>>>>>>
>>>>>>>> :ConstructPerson a sp:Construct ;
>>>>>>>>         sp:text """
>>>>>>>> PREFIX  foaf: <http://xmlns.com/foaf/0.1/>
>>>>>>>> PREFIX  acl:  <http://www.w3.org/ns/auth/acl#>
>>>>>>>>
>>>>>>>> CONSTRUCT
>>>>>>>>       {
>>>>>>>>         ?this a foaf:Person .
>>>>>>>>         ?this foaf:name ?name .
>>>>>>>>         ?this ?p ?o .
>>>>>>>>       }
>>>>>>>> WHERE
>>>>>>>>       {   { ?this  a                     foaf:Person ;
>>>>>>>>                    foaf:name             ?name
>>>>>>>>           }
>>>>>>>>         UNION
>>>>>>>>           { GRAPH <acl>
>>>>>>>>               { ?auth  acl:accessTo  ?this ;
>>>>>>>>                      acl:agent ?agent .
>>>>>>>>               }
>>>>>>>>             ?this  ?p  ?o
>>>>>>>>           }
>>>>>>>>       }
>>>>>>>>         """ ;
>>>>>>>>         rdfs:isDefinedBy : .
>>>>>>>>
>>>>>>>> The idea is that the person query always returns "basic" properties,
>>>>>>>> and adds all properties *only* if the agent ?agent has an
>>>>>>>> authorization to access the requested resource ?this.
>>>>>>>> This approach requires that the query has access to the ACL data,
>>>>>>>> which I have indicated here as GRAPH <acl>. The actual pattern for
>>>>>>>> authorization check will probably be more complex of course.
>>>>>>>> It also requires that the authentication mechanism can provide
>>>>>>>> the URI
>>>>>>>> of the agent.
>>>>>>>>
>>>>>>>> I hope I got what you meant :)
>>>>>>>>
>>>>>>>> On Fri, Sep 13, 2019 at 2:58 PM Mikael Pesonen
>>>>>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>>>>>> Ah, I might have explained our case bit vaguely. So I just meant
>>>>>>>>> that we
>>>>>>>>> have in RDF data one kind of person resources, and
>>>>>>>>> depending on the access rights in the application, you are
>>>>>>>>> allowed to
>>>>>>>>> see different portions of that person's data.
>>>>>>>>> Basic user sees only the name, for example, and admin user is
>>>>>>>>> allowed to
>>>>>>>>> see all data. This is handled by selecting different template
>>>>>>>>> for basic
>>>>>>>>> user and admin, right?
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 13/09/2019 15:52, Martynas Jusevičius wrote:
>>>>>>>>>> Mikael,
>>>>>>>>>>
>>>>>>>>>> this is related to hierarchical URIs:
>>>>>>>>>> http://patterns.dataincubator.org/book/hierarchical-uris.html
>>>>>>>>>>
>>>>>>>>>> In your case, the question is how you have organized the
>>>>>>>>>> collections/items of basic and admin persons in your dataset.
>>>>>>>>>>
>>>>>>>>>> One option is that both "basic persons" and "admin persons"
>>>>>>>>>> belong to
>>>>>>>>>> the same collection and have a single URI pattern: /persons/{id}
>>>>>>>>>> In this case you cannot tell if resource /persons/12345 is a
>>>>>>>>>> "basic
>>>>>>>>>> person" or "admin person" just from its URI. You need to
>>>>>>>>>> dereference
>>>>>>>>>> it and the look into RDF types and properties.
>>>>>>>>>>
>>>>>>>>>> Another option is that you treat them as belonging to separate
>>>>>>>>>> collections, for example: /persons/{id} and /admins/{id}
>>>>>>>>>> In this case you can easily tell if a resource is a "basic
>>>>>>>>>> person" or
>>>>>>>>>> an "admin person" already from its URIs.
>>>>>>>>>>
>>>>>>>>>> Linked Data Templates are best suited for this second case,
>>>>>>>>>> where URI
>>>>>>>>>> space is subdivided into hierarchies based on entity types.
>>>>>>>>>> That makes
>>>>>>>>>> it easy to define URI templates that match precisely the set of
>>>>>>>>>> resources that you want.
>>>>>>>>>>
>>>>>>>>>> Does it make it clearer?
>>>>>>>>>>
>>>>>>>>>> On Fri, Sep 13, 2019 at 2:08 PM Mikael Pesonen
>>>>>>>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>>>>>>>> Hi Martynas,
>>>>>>>>>>>
>>>>>>>>>>> thank you for the examples, GET seems clear now.
>>>>>>>>>>>
>>>>>>>>>>> Good point about the person / document. We probably end up
>>>>>>>>>>> with three
>>>>>>>>>>> kind of resources: actual object, admin record (who last
>>>>>>>>>>> modified etc),
>>>>>>>>>>> and web page or another document about the object.
>>>>>>>>>>>
>>>>>>>>>>> Just one question: what did you mean by
>>>>>>>>>>>
>>>>>>>>>>> "If you cannot distinguish "basic person" from "admin person"
>>>>>>>>>>> by their
>>>>>>>>>>> URIs"?
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> We are not quite there yet with updates, so we might have
>>>>>>>>>>> questions
>>>>>>>>>>> later about those.
>>>>>>>>>>>
>>>>>>>>>>> Br,
>>>>>>>>>>> Mikael
>>>>>>>>>>>
>>>>>>>>>>> On 11/09/2019 18:45, Martynas Jusevičius wrote:
>>>>>>>>>>>> Hi Mikael,
>>>>>>>>>>>>
>>>>>>>>>>>> thanks for reaching out.
>>>>>>>>>>>>
>>>>>>>>>>>> There is more information on LDT in the AtomGraph Processor
>>>>>>>>>>>> wiki, more
>>>>>>>>>>>> specifically:
>>>>>>>>>>>> https://github.com/AtomGraph/Processor/wiki/Linked-Data-Templates
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> The matching is based on URIs: relative request URI is being
>>>>>>>>>>>> matched
>>>>>>>>>>>> against the ldt:match values of templates in the ontology.
>>>>>>>>>>>>
>>>>>>>>>>>> Then, from the matching template (if there is any), the
>>>>>>>>>>>> SPARQL command
>>>>>>>>>>>> is retrieved using either ldt:query or ldt:update (depending
>>>>>>>>>>>> on the
>>>>>>>>>>>> HTTP request method).
>>>>>>>>>>>>
>>>>>>>>>>>> To address your example, templates and queries could look
>>>>>>>>>>>> like this:
>>>>>>>>>>>>
>>>>>>>>>>>> :BasicPersonItem a ldt:Template ;
>>>>>>>>>>>>           ldt:match "/person/basic/{id}" ;
>>>>>>>>>>>>           ldt:query :ConstructBasicPerson ;
>>>>>>>>>>>>           rdfs:isDefinedBy : .
>>>>>>>>>>>>
>>>>>>>>>>>> :ConstructBasicPerson a sp:Construct ;
>>>>>>>>>>>>           sp:text """
>>>>>>>>>>>>           PREFIX  foaf: <http://xmlns.com/foaf/0.1/>
>>>>>>>>>>>>
>>>>>>>>>>>>           CONSTRUCT
>>>>>>>>>>>>           {
>>>>>>>>>>>>               ?this a foaf:Person ;
>>>>>>>>>>>>                   foaf:name ?name .
>>>>>>>>>>>>           }
>>>>>>>>>>>>           {
>>>>>>>>>>>>               ?this a foaf:Person ;
>>>>>>>>>>>>                   foaf:name ?name .
>>>>>>>>>>>>           }
>>>>>>>>>>>>           """ ;
>>>>>>>>>>>>           rdfs:isDefinedBy : .
>>>>>>>>>>>>
>>>>>>>>>>>> :AdminPersonItem a ldt:Template ;
>>>>>>>>>>>>           ldt:match "/person/admin/{id}" ;
>>>>>>>>>>>>           ldt:query :ConstructAdminPerson ;
>>>>>>>>>>>>           rdfs:isDefinedBy : .
>>>>>>>>>>>>
>>>>>>>>>>>> :ConstructAdminPerson a sp:Construct ;
>>>>>>>>>>>>           sp:text """
>>>>>>>>>>>>           CONSTRUCT WHERE
>>>>>>>>>>>>           {
>>>>>>>>>>>>               ?this ?p ?o
>>>>>>>>>>>>           }
>>>>>>>>>>>>           """ ;
>>>>>>>>>>>>           rdfs:isDefinedBy : .
>>>>>>>>>>>>
>>>>>>>>>>>> "Basic person" query retrieves only name and type, "admin
>>>>>>>>>>>> person"
>>>>>>>>>>>> query retrieves all properties.
>>>>>>>>>>>> This example requires that basic and admin person resources
>>>>>>>>>>>> can be
>>>>>>>>>>>> differentiated by their URIs, i.e. "/person/basic/{id}" vs
>>>>>>>>>>>> "/person/admin/{id}".
>>>>>>>>>>>>
>>>>>>>>>>>> It also assumes that persons are documents (since they can be
>>>>>>>>>>>> dereferenced over HTTP), which is not kosher re. httpRange-14
>>>>>>>>>>>> [1]. A
>>>>>>>>>>>> better solution would have separate resources for persons
>>>>>>>>>>>> e.g. using
>>>>>>>>>>>> hash URIs such as #this) and explicitly connect them to
>>>>>>>>>>>> documents
>>>>>>>>>>>> using an RDF property. We use
>>>>>>>>>>>> foaf:primaryTopic/foaf:isPrimaryTopicOf.
>>>>>>>>>>>> But this is a whole topic on its own.
>>>>>>>>>>>>
>>>>>>>>>>>> If you cannot distinguish "basic person" from "admin person"
>>>>>>>>>>>> by their
>>>>>>>>>>>> URIs, you could also have a template that matches both and
>>>>>>>>>>>> maps to a
>>>>>>>>>>>> single query. The question is then whether you can
>>>>>>>>>>>> differentiate which
>>>>>>>>>>>> properties to return using a single query.
>>>>>>>>>>>>
>>>>>>>>>>>> Does this help?
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> [1] https://www.w3.org/2001/tag/group/track/issues/14
>>>>>>>>>>>>
>>>>>>>>>>>> Martynas
>>>>>>>>>>>> atomgraph.com
>>>>>>>>>>>>
>>>>>>>>>>>> On Wed, Sep 11, 2019 at 11:21 AM Mikael Pesonen
>>>>>>>>>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>>>>>>>>>> Hi Martynas,
>>>>>>>>>>>>>
>>>>>>>>>>>>> we have a proprietary implementation now:
>>>>>>>>>>>>>
>>>>>>>>>>>>> js/React app generates a custom json out of form data. That
>>>>>>>>>>>>> is sent
>>>>>>>>>>>>> (with a template id) to also custom proxy, which converts
>>>>>>>>>>>>> the json into
>>>>>>>>>>>>> SPARQL using pre made templates. SPARQL is then queried on
>>>>>>>>>>>>> Apache Jena.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Now we would like to replace all custom bits with one ore
>>>>>>>>>>>>> more standards.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Is it possible to have any kind of templates with LDT? For
>>>>>>>>>>>>> example
>>>>>>>>>>>>> "person_basic" and "person_admin",
>>>>>>>>>>>>> where admin contains more properties of a person?
>>>>>>>>>>>>>
>>>>>>>>>>>>> I'm still having trouble to understand how the SPARQL
>>>>>>>>>>>>> template is
>>>>>>>>>>>>> selected with LDT.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Br,
>>>>>>>>>>>>> Mikael
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 10/09/2019 15:50, Martynas Jusevičius wrote:
>>>>>>>>>>>>>> Hey Mikael,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> we have a simple example here:
>>>>>>>>>>>>>> https://github.com/AtomGraph/Processor#example
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Do you have some specific use case in mind? If you can
>>>>>>>>>>>>>> share it, I can
>>>>>>>>>>>>>> probably look into it.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> There is a Community Group for Linked Data Templates which
>>>>>>>>>>>>>> includes a
>>>>>>>>>>>>>> mailing list: https://www.w3.org/community/declarative-apps/
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Martynas
>>>>>>>>>>>>>> atomgraph.com
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Tue, Sep 10, 2019 at 1:27 PM Mikael Pesonen
>>>>>>>>>>>>>> <mikael.pesonen@lingsoft.fi> wrote:
>>>>>>>>>>>>>>> In the example there is the GET request
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> GET
>>>>>>>>>>>>>>> /people/Berners-Lee?g=http%3A%2F%2Flinkeddatahub.com%2Fgraphs%2Fc5f34fe9-0456-48e8-a371-04be71529762
>>>>>>>>>>>>>>> HTTP/1.1
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Often you want to query different amounts of data
>>>>>>>>>>>>>>> depending of the case. Sometimes for example, person name
>>>>>>>>>>>>>>> is enough, other time you want all the triples (DESCRIBE).
>>>>>>>>>>>>>>> How do you specify here the context?
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> BTW is there a dedicated forum for discussing Linked Data
>>>>>>>>>>>>>>> Templates?
>>>>>>>>>>>>> --
>>>>>>>>>>>>> Lingsoft - 30 years of Leading Language Management
>>>>>>>>>>>>>
>>>>>>>>>>>>> www.lingsoft.fi
>>>>>>>>>>>>>
>>>>>>>>>>>>> Speech Applications - Language Management - Translation -
>>>>>>>>>>>>> Reader's and Writer's Tools - Text Tools - E-books and M-books
>>>>>>>>>>>>>
>>>>>>>>>>>>> Mikael Pesonen
>>>>>>>>>>>>> System Engineer
>>>>>>>>>>>>>
>>>>>>>>>>>>> e-mail: mikael.pesonen@lingsoft.fi
>>>>>>>>>>>>> Tel. +358 2 279 3300
>>>>>>>>>>>>>
>>>>>>>>>>>>> Time zone: GMT+2
>>>>>>>>>>>>>
>>>>>>>>>>>>> Helsinki Office
>>>>>>>>>>>>> Eteläranta 10
>>>>>>>>>>>>> FI-00130 Helsinki
>>>>>>>>>>>>> FINLAND
>>>>>>>>>>>>>
>>>>>>>>>>>>> Turku Office
>>>>>>>>>>>>> Kauppiaskatu 5 A
>>>>>>>>>>>>> FI-20100 Turku
>>>>>>>>>>>>> FINLAND
>>>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Lingsoft - 30 years of Leading Language Management
>>>>>>>>>>>
>>>>>>>>>>> www.lingsoft.fi
>>>>>>>>>>>
>>>>>>>>>>> Speech Applications - Language Management - Translation -
>>>>>>>>>>> Reader's and Writer's Tools - Text Tools - E-books and M-books
>>>>>>>>>>>
>>>>>>>>>>> Mikael Pesonen
>>>>>>>>>>> System Engineer
>>>>>>>>>>>
>>>>>>>>>>> e-mail: mikael.pesonen@lingsoft.fi
>>>>>>>>>>> Tel. +358 2 279 3300
>>>>>>>>>>>
>>>>>>>>>>> Time zone: GMT+2
>>>>>>>>>>>
>>>>>>>>>>> Helsinki Office
>>>>>>>>>>> Eteläranta 10
>>>>>>>>>>> FI-00130 Helsinki
>>>>>>>>>>> FINLAND
>>>>>>>>>>>
>>>>>>>>>>> Turku Office
>>>>>>>>>>> Kauppiaskatu 5 A
>>>>>>>>>>> FI-20100 Turku
>>>>>>>>>>> FINLAND
>>>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Lingsoft - 30 years of Leading Language Management
>>>>>>>>>
>>>>>>>>> www.lingsoft.fi
>>>>>>>>>
>>>>>>>>> Speech Applications - Language Management - Translation -
>>>>>>>>> Reader's and Writer's Tools - Text Tools - E-books and M-books
>>>>>>>>>
>>>>>>>>> Mikael Pesonen
>>>>>>>>> System Engineer
>>>>>>>>>
>>>>>>>>> e-mail: mikael.pesonen@lingsoft.fi
>>>>>>>>> Tel. +358 2 279 3300
>>>>>>>>>
>>>>>>>>> Time zone: GMT+2
>>>>>>>>>
>>>>>>>>> Helsinki Office
>>>>>>>>> Eteläranta 10
>>>>>>>>> FI-00130 Helsinki
>>>>>>>>> FINLAND
>>>>>>>>>
>>>>>>>>> Turku Office
>>>>>>>>> Kauppiaskatu 5 A
>>>>>>>>> FI-20100 Turku
>>>>>>>>> FINLAND
>>>>>>>>>
>>>>>>> --
>>>>>>> Lingsoft - 30 years of Leading Language Management
>>>>>>>
>>>>>>> www.lingsoft.fi
>>>>>>>
>>>>>>> Speech Applications - Language Management - Translation - Reader's
>>>>>>> and Writer's Tools - Text Tools - E-books and M-books
>>>>>>>
>>>>>>> Mikael Pesonen
>>>>>>> System Engineer
>>>>>>>
>>>>>>> e-mail: mikael.pesonen@lingsoft.fi
>>>>>>> Tel. +358 2 279 3300
>>>>>>>
>>>>>>> Time zone: GMT+2
>>>>>>>
>>>>>>> Helsinki Office
>>>>>>> Eteläranta 10
>>>>>>> FI-00130 Helsinki
>>>>>>> FINLAND
>>>>>>>
>>>>>>> Turku Office
>>>>>>> Kauppiaskatu 5 A
>>>>>>> FI-20100 Turku
>>>>>>> FINLAND
>>>>>>>
>>>>> --
>>>>> Lingsoft - 30 years of Leading Language Management
>>>>>
>>>>> www.lingsoft.fi
>>>>>
>>>>> Speech Applications - Language Management - Translation - Reader's
>>>>> and Writer's Tools - Text Tools - E-books and M-books
>>>>>
>>>>> Mikael Pesonen
>>>>> System Engineer
>>>>>
>>>>> e-mail: mikael.pesonen@lingsoft.fi
>>>>> Tel. +358 2 279 3300
>>>>>
>>>>> Time zone: GMT+2
>>>>>
>>>>> Helsinki Office
>>>>> Eteläranta 10
>>>>> FI-00130 Helsinki
>>>>> FINLAND
>>>>>
>>>>> Turku Office
>>>>> Kauppiaskatu 5 A
>>>>> FI-20100 Turku
>>>>> FINLAND
>>>>>
>> --
>> Lingsoft - 30 years of Leading Language Management
>>
>> www.lingsoft.fi
>>
>> Speech Applications - Language Management - Translation - Reader's and Writer's Tools - Text Tools - E-books and M-books
>>
>> Mikael Pesonen
>> System Engineer
>>
>> e-mail: mikael.pesonen@lingsoft.fi
>> Tel. +358 2 279 3300
>>
>> Time zone: GMT+2
>>
>> Helsinki Office
>> Eteläranta 10
>> FI-00130 Helsinki
>> FINLAND
>>
>> Turku Office
>> Kauppiaskatu 5 A
>> FI-20100 Turku
>> FINLAND
>>

-- 
Lingsoft - 30 years of Leading Language Management

www.lingsoft.fi

Speech Applications - Language Management - Translation - Reader's and Writer's Tools - Text Tools - E-books and M-books

Mikael Pesonen
System Engineer

e-mail: mikael.pesonen@lingsoft.fi
Tel. +358 2 279 3300

Time zone: GMT+2

Helsinki Office
Eteläranta 10
FI-00130 Helsinki
FINLAND

Turku Office
Kauppiaskatu 5 A
FI-20100 Turku
FINLAND

Received on Tuesday, 17 September 2019 12:27:06 UTC