op-ted / model2owl Goto Github PK
View Code? Open in Web Editor NEWTransform UML into a formal OWL ontology and SHACL shapes
Home Page: https://meaningfy-ws.github.io/model2owl-docs
License: European Union Public License 1.2
Transform UML into a formal OWL ontology and SHACL shapes
Home Page: https://meaningfy-ws.github.io/model2owl-docs
License: European Union Public License 1.2
Most (all?) object props in owl-shapes-ePO-CM-v2.0.2-2020-11-06 have a shape check like this:
epo:Subcontract a sh:NodeShape ;
sh:sparql [ sh:select
""" SELECT ?this ?that WHERE
{ ?this <http://data.europa.eu/a4g/ontology#acceptsProposalOf> ?that .
?that <http://data.europa.eu/a4g/ontology#acceptsProposalOf> ?this .} """ ] ;
But the majority (all) have class restrictions, so such cyclicity is not possible or likely.
So why perform this check on every object prop?
Furthermore, epo:acceptsProposalOf is not declared owl:AsymmetricProperty in owl-restriction-ePO-CM-v2.0.2-2020-11-06 (other props are declared Asymmetric), so what's the justification for doing this check?
Ontology metadata uses a timestamp in xsd:date, which is not really useful:
"2020-11-07+01:00"^^<http://www.w3.org/2001/XMLSchema#date>
(Ok, this is nitpicking)
The comment on eg InnovativeProcurement
is busy and overloaded:
An instance of the class InnovativeProcurement is represented in eForms with the code "inn-pur" defined in the codelist strategic-procurement.
Research (21/01/2020):
Purchasing and early adoption of solutions which are not yet available on large scale commercial basis.
Source: Adapted from the Digital Single Market's Policy on Public Procurement of Innovative Solutions. https://ec.europa.eu/digital-single-market/en/public-procurement-innovative-solutions
Additional Information:
‘innovation’ means the implementation of a new or significantly improved product, service or process, including but not limited to production, building or construction processes, a new marketing method, or a new organisational method in business practices, workplace organisation or external relations inter alia with the purpose of helping to solve societal challenges or to support the Europe 2020 strategy for smart, sustainable and inclusive growth;
See: Directive 2014/24
Articles: 2, 26 (3), 31, 67 (2.a)
Question:
Is Pre-Commercial Procurement (PCP) another type of Strategic Procurement?
The UML Conventions should specify additional kinds of notes (as are available eg in SKOS) so this can be structured better. Eg like this:
skos:definition ""An instance of the class InnovativeProcurement is represented in eForms with the code "inn-pur" defined in the codelist strategic-procurement.
### TODO: not sure what to map this comment to, so leaving it here. Surely the comment below describes the entity better ###
Research (21/01/2020):
Purchasing and early adoption of solutions which are not yet available on large scale commercial basis.""";
dc:source """Adapted from the Digital Single Market's Policy on Public Procurement of Innovative Solutions.""",
<https://ec.europa.eu/digital-single-market/en/public-procurement-innovative-solutions>;
skos:scopeNote """‘innovation’ means the implementation of a new or significantly improved product, service or process, including but not limited to production, building or construction processes, a new marketing method, or a new organisational method in business practices, workplace organisation or external relations inter alia with the purpose of helping to solve societal challenges or to support the Europe 2020 strategy for smart, sustainable and inclusive growth;"
dc:source """Directive 2014/24,
Articles: 2, 26 (3), 31, 67 (2.a)""";
skos:editorialNote """Question:
Is Pre-Commercial Procurement (PCP) another type of Strategic Procurement?""".
Dear @costezki ,
when a property has multiple domain, most possibly disjoint, does the transformation artefact specifies which are these domains or it just leaves the domain restriction non-specified?
This is related to the Application Profile:
When in the Conceptual Model there is a class of one namespace, with data properties of another namespace. See example:
When producing the restrictions, shacl and owl files, these data properties are created in the class namespace, instead of their own namespace.
For example, reg2015:AdditionalInformation is created in http://data.europa.eu/a4g/extension/ontology#hasAdditionalInformation.
The object properties are created in the expected namespace.
In case you need an example, here you have the XMI: https://github.com/eprocurementontology/eprocurementontology/tree/v2.0.1/v2.0.1/03-Analysis%20and%20design/EA-Conceptual%20Model/Reg2015-ApplicationProfile/XMI
The class epo:ResultNotice
is defined in the restrictions file but not in the core.
Some prefixes (xsd rdf rdfs owl
, maybe skos
) should be predefined and used.
Else eg owl-core-ePO-CM-v2.0.2-2020-11-06.rdf doesn't use xsd:
CURIEs but full URLs, eg <http://www.w3.org/2001/XMLSchema#Time>
Prefix-related comments on ePO_owl_core.ttl.
See OP-TED/ePO#392 on how it was made; see https://gist.github.com/VladimirAlexiev/c1f8797b4412df0708b41f90f512862a for a list of its terms.
dc, epor, epos
, and empty prefix :
(equal to epo:
)http://data.europa.eu/m8g/
that's not defined as a prefix. Comments suggest multiple prefixes should be defined and used: cccev, cpov
, etchttp://unknown.domain/for/prefix#
that's obviously not intended. Corresponds to cpv, locn
http://www.w3.org/ns/locn#
appears in fullhttp://www.w3.org/2006/time#
appears in fullxsd
is not defined so datatypes appear in fullxsd
datatypes (6 terms), especially since you misspelled the local name: http://www.w3.org/2001/XMLSchema#Boolean should be in lowercaseePO-SHACL:
There are no shapes for the CCTS classes.
Also All attributes of the CCTS classes have cardinality 1. Thus, all attributes are mandatory. As discussed with SEGURA FERNÁNDEZ-CARNICERO Juan Carlos this is a task to be done for version 2.0.2 of the Conceptual Model.
Create a custom script that would generate the ePO ontology documentation. It shall consider the
The shapes and restriction ontologies define the empty prefix, which is IMHO a bad practice.
They also define derived prefixes epos, epor
but use them only once (or not at all):
## owl-shapes-ePO-CM-v2.0.2-2020-11-06
@prefix : <http://data.europa.eu/a4g/shape#> .
@prefix epos: <http://data.europa.eu/a4g/shape#> .
owl:versionIRI :ePO-CM-v2.0.2-2020-11-06.eap.xmi-2020-11-07 ;
## owl-restriction-ePO-CM-v2.0.2-2020-11-06
@prefix : <http://data.europa.eu/a4g/rule#> .
@prefix epor: <http://data.europa.eu/a4g/rule#> .
@prefix epos: <http://data.europa.eu/a4g/shape#> .
owl:versionIRI epor:ePO-CM-v2.0.2-2020-11-06.eap.xmi-2020-11-07 ;
Please omit all these prefixes, and just emit a full URL in owl:versionIRI.
WHY: many repos (including GraphDB) remember ingested prefixes as "namespaces" (there are rdf4j calls to handle namespaces), so you should avoid namespace pollution.
ePO-SHACL:
The SPARQL shapes should have the variable ?this, instead of $this. As defined in the specification: https://www.w3.org/TR/shacl/#sparql-constraints-prebound
in the object properties where a code should be specified, the range is both code (lower case letters see issue #59) and a class that represents the specific skos:ConceptScheme (and here there is a doubt, see below).
I think we have two possibilities:
Thus object properties such as "hasAdditionalClassification", "hasMainClassification", "hasAwardStatus", "hasBuyerLegalType" will have only one range: in case of 1 the range will be Code, in case of 2) the name of the specific class that represents the specific controlled vocabulary to be used in the object property.
BTW: If I take the Cpv class it says that is equivalent to skos:inScheme value Cpv. So Cpv is a ConceptScheme or a Concept? Because if I have an object property "hasMainClassification" the range should point to a single concept CPV, not to the overall ConceptScheme.
Finally, I am not sure that the property "hasAdditionalClassification" is functional.
I guess someone quite contravened your UML Conventions with this prop because it's wildly polymorphic:
epo:appliesTo
rdfs:domain [ a owl:Class ;
owl:unionOf ( epo:DesignContestRegimeTerm epo:SecurityClearanceTerm epo:FollowupContractTerm epo:FrameworkAgreementTerm epo:ReviewTerm epo:SelectionCriterion epo:ProcurementCriterionProperty epo:TenderLot epo:ContractTerm )
] ;
rdfs:range [ a owl:Class ;
owl:unionOf ( epo:Lot epo:Document epo:LotGroup <http://www.w3.org/ns/org#Site> epo:Winner )
] ;
There are desired domain-range correlations, eg: ReviewTerm appliesTo Lot
, SecurityClearanceTerm appliesTo org:Site
.
They are captured in "shapes" but not in "restriction". You should also emit them in "restriction" by using onProperty
.
A few props in owl-restriction-ePO-CM-v2.0.2-2020-11-06 have domains/ranges that consist of a singleton (i.e. useless) union:
epo:isQualifiedBy
rdfs:range [ a owl:Class ;
owl:unionOf ( epo:QualificationSystem )
] .
epo:isReferedByA
rdfs:range [ a owl:Class ;
owl:unionOf ( epo:Contract )
] .
epo:isUsedToAward
rdfs:domain [ a owl:Class ;
owl:unionOf ( epo:AwardCriterion )
] ;
This is strange since many other props have normal single-class domains and ranges
ePO_restrictions release 2.0.1:
<http://www.w3.org/ns/org#Site>
a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
owl:cardinality 1 ;
owl:onProperty epo:hasPostalAddress
] ;
rdfs:subClassOf [ a owl:Restriction ;
owl:cardinality 1 ;
owl:onProperty epo:hasPostalAddress
] .
This prop in owl-restriction-ePO-CM-v2.0.2-2020-11-06 has two domains and ranges.
epo:hasWeightValueType
a owl:FunctionalProperty ;
rdfs:domain [ a owl:Class ;
owl:unionOf ( epo:AwardCriterion epo:SelectionCriterion )
] ;
rdfs:domain [ a owl:Class ;
owl:unionOf ( epo:AwardCriterion epo:SelectionCriterion epo:WeightValueAwardCriterion )
] ;
rdfs:range <http://www.unece.org/cefact#code> ;
rdfs:range [ a owl:Class ;
owl:unionOf ( <http://publications.europa.eu/resource/authority/Number-weight> )
] .
I think this is a mistake since it infers the source/target of every prop instance to have 2 classes, which is probably not intended:
domain
: the first one is superfluous since it's subsumed by the second onerange
: the target node of epo:hasWeightValueType will be inferred to be both cefact:code and aut:Number-weightowl:import is by no means free, so please omit imports that you don't need.
You can use terms of an ontology without importing it!
You need to import only if you need inference from the imported ontology.
<http://data.europa.eu/a4g/shape> owl:imports
<http://www.w3.org/2004/02/skos/core> , # NOT used
<http://datashapes.org/dash> , # NOT used
dct: , # NOT needed, only dct:date used
<http://data.europa.eu/a4g/ontology> , # MAYBE is needed
sh: ; # many terms used but no inference is needed
owl-shapes-ePO-CM-v2.0.2-2020-11-06.rdf has this (in turtle):
epo:Subcontract a sh:NodeShape ;
sh:property [ a sh:PropertyShape ;
sh:maxCount 1 ;
sh:name "Accepts proposal of" ;
sh:path epo:acceptsProposalOf
] ;
sh:property [ a sh:PropertyShape ;
sh:class epo:AwardDecision ;
sh:name "Accepts proposal of" ;
sh:path epo:acceptsProposalOf
] ;
Cannot you merge the two sh:property into one?
owl-restriction-ePO-CM-v2.0.2-2020-11-06 includes some restrictions that are useless because they don't really restrict anything:
epo:AccessTerm a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
owl:onProperty epo:hasRestrictedProcurementDocumentsMadeAvailableVia
] ;
Also, the prop definition already says more:
epo:hasRestrictedProcurementDocumentsMadeAvailableVia
rdfs:domain epo:AccessTerm ;
rdfs:range epo:Channel .
And this restriction:
epo:Agent a owl:Class ;
rdfs:subClassOf [ a owl:Restriction ;
owl:maxCardinality 1 ;
owl:onProperty epo:usesBuyerProfile
] ;
epo:usesBuyerProfile rdfs:domain epo:Agent ;
rdfs:range epo:BuyerProfile .
is better (more simply) represented as
epo:usesBuyerProfile a owl:FunctionalProperty
rdfs:domain epo:Agent ;
rdfs:range epo:BuyerProfile .
You use owl:FunctionalProperty on other props, so why not here?
UC big glossary:
Technical approaches:
model2owl.glossary
script(Maybe related to #136, and worse than it)
This is a serious bug in the generator:
epo:address rdfs:domain dct:Location ;
rdfs:domain [ rdf:type owl:Class ;
owl:unionOf ( <http://www.w3.org/ns/org#Organization> <http://data.europa.eu/m8g/ContactPoint> )
] ;
rdfs:range <http://www.w3.org/ns/locn#Address> ;
rdfs:range [ rdf:type owl:Class ;
owl:unionOf ( <http://www.w3.org/ns/locn#Address> )
] .
According to RDF semantics, every triple s epo:addres o
will lead to these inferences:
s
is dct:Location
and also an anonymous type being unionOf
two other typeso
is locn:Address
and also an anonymous type being a singleton unionOf
When in the UML an object property extends (or is equivalent to) another, does the transformation artefact specify the parent property of the sub-property?
When executing the current SHACL shapes, we found out that the SPARQL queries referring to an ePO class, do not have the ePO prefix, so they throw an exception "Invalid SPARQL constraint".
For example, there is the following SPARQL query:
<sh:sparql rdf:parseType="Resource">
sh:selectSELECT $this WHERE { $this a Notice . }
</sh:select>
</sh:sparql>
The Notice should be epo:Notice, and include the prefix to the sh:sparql property. The shape would be similar to:
<sh:sparql rdf:parseType="Resource">
sh:selectSELECT $this WHERE { $this a epo:Notice . }
</sh:select>
<sh:prefixes >
<rdf:Description rdf:about="http://example.com/ns#">
<sh:declare rdf:parseType="Resource">
<sh:namespace rdf:datatype="http://www.w3.org/2001/XMLSchema#anyURI"
>http://data.europa.eu/a4g/ontology#</sh:namespace>
sh:prefixepo</sh:prefix>
</sh:declare>
</rdf:Description>
</sh:prefixes>
</sh:sparql>
There are two properties named "hasAvailabilityRestriction": one with domain Channel and another one with domain ContactPoint.
Probably it should be one property with domain Channel or ContactPoint and range OpeningHoursSpecification
Are you looking for feedback on UML Conventions Report that I'm reading at https://rawgit2.com/OP-TED/ePO/master/implementation/ePO/conventions_report/conventions_report.html ?
(I could write plenty more)
ePO-SHACL:
The data properties of type Text, have two shapes to indicate that the datatype must be a rdf:langString AND a ccts:Text. This should be changed to either
An example of these shapes:
<sh:property>
<sh:PropertyShape>
<sh:path rdf:resource="http://data.europa.eu/a4g/ontology#hasFax"/>
<sh:name>Fax</sh:name>
<sh:datatype rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"/>
</sh:PropertyShape>
</sh:property>
<sh:property>
<sh:PropertyShape>
<sh:path rdf:resource="http://data.europa.eu/a4g/ontology#hasFax"/>
<sh:name>Fax</sh:name>
<sh:class rdf:resource="http://www.unece.org/cefact#Text"/>
</sh:PropertyShape>
</sh:property>
AFAIK the ePO conventions including prop naming are at https://github.com/meaningfy-ws/model2owl/blob/master/doc/uml-conventions/uml-conventions.pdf (related to https://github.com/OP-TED/model2owl by @costezki)
Also, @giorgialodi commented:
there are conventions on the naming of the properties (e.g., use of a verb in object properties).
Yes, "use of a verb in object properties" is an often used convention. But it's not strictly followed in ePO!
Eg these are data props that use the "has" prefix:
There's no way to tell what these props are (i.e. what is their object) just by looking at the name. (The former is a boolean and the latter a string.) IMHO:
Examples of fixes needed:
isSMESuitable
numberOfAbnormallyLowTenderLots
isAccelerated
numberOfTenderersInvited
epo:Value
:
vatPercentage
maximumAmount
minimumAmount
isVATIncluded
overallAmount
I think we need to state some general principles that lead the evolution of this great work. Here I list a couple of principles that could be included:
If we only are capable of implementing these two features, then there are plenty of possibilities arising in front of us, like the possibility of intgrating the script directly inside the UML designer tool, or producing a microservice that takes in the EAP file (or the XMI) and the type of artefacts desired, and responds with the artefacts (or a graph directly constructed/inserted in a Graph Store, etc.).
I have some ideas on how these two features could be implemented
KR
The property has a domain which is "CountryIdentification or FinancialAccount" , FinancialAccount and a double range code, Country.
Probably the domain should be only "CountryIdentification or FinancialAccount" and the range according to #60
BTW: the CountryIdentification class is no longer available in version 2.0.2 since it did not make sense modelled as it is in version 2.0.1. We should delete it also in the OWL files for version 2.0.1. I will open an issue in the other repository.
Here are some examples of domains/ranges that use singleton owl:unionOf
epo:isSubordinatedToContract
rdfs:range [ rdf:type owl:Class ;
owl:unionOf ( epo:Contract )
] .
epo:isSupportedBy rdfs:domain [ rdf:type owl:Class ;
owl:unionOf ( epo:Tender )
] ;
This is unusual and cruel (you seem to assume owl:unionOf
is "free", which is not at all the case).
This seems to be a peculiar bug in the generator since there are examples of properly formatted single domain and range (even when objects), eg:
epo:paidReviewRequestFee
rdfs:domain epo:ReviewRequest ;
rdfs:range epo:MonetaryValue .
@prefix dc: <http://www.omg.org/spec/UML/20131001/UMLDC> .
@prefix dct: <http://purl.org/dc/terms/> .
But everyone knows that dc:
means the following (see https://prefix.cc/dc.ttl):
@prefix dc: <http://purl.org/dc/elements/1.1/>.
Either correct or remove this prefix (which is not used anyway)
The restrictions file does not show that Contract or ContractModificationNotice are subclasses of Document and the ‘disjointness’ is not indicated.
owl-shapes-ePO-CM-v2.0.2-2020-11-06 repeats a bunch of term metadata that's in owl-core-ePO-CM-v2.0.2-2020-11-06:
rdfs:comment "A voluntary, deliberate, and legally binding agreement between two or more competent parties.\n\n(WG approval 01/06/2018)"@en ;
rdfs:isDefinedBy <http://data.europa.eu/a4g/ontology> ;
rdfs:label "Contract"@en ;
sh:description "A voluntary, deliberate, and legally binding agreement between two or more competent parties.\n\n(WG approval 01/06/2018)" ;
sh:name "Contract" ;
I think you should not do that.
Only sh:name is not repeated as a prop, but because you use the same label (minus lang tag), it is de-facto repeated and better be skipped.
Furthermore, it repeats some ontology metadata that should be skipped (it has no business of defining the VANN of another ontology):
<http://data.europa.eu/a4g/shape>
vann:preferredNamespacePrefix "epo" ;
vann:preferredNamespaceUri "http://data.europa.eu/a4g/ontology#" ;
As discussed with @costezki in a recent call, in the last version of the OWL restriction file (version 07/12) restrictions do not specify the type of range. Therefore, in software like Protégé restrictions are attributed to generic "owl:Thing" when it is an object property or to "rdfs:Literal" when it is a datatype property.
I think it is important to specify the type of the range of the object and data type restrictions.
See screenshot for the class Procedure:
In this case for instance the property hasAccelerated should be exactly 1 xsd:boolean (in the ideal world probably is max 1 xsd:boolean but this has to be fixed at the modelling level) or hasID should be exactly 1 Identifier etc.
Dear,
I've noticed that domain/range axioms, everytime they involve more than a concept (i.e., two or more), are always specified as INTERSECTIONS (as it is by default in Protégé). However, it seems to me that, most of the cases, the intended meaning would be that of UNIONS, such as in the following:
Maybe I'm wrong but, I don't think that the idea here was the one of specifying the range of this property as the intersection of the listed concetps. Am I wrong?
Similarly in the following:
Is it really the intersection of 'FinancialAccount' and 'FundsIdentification' what we want to specify as the domain of the property 'hasName'?
If, instead, we mean to have domains and ranges specified as unions of concepts, of course we can do it, even if in Protégé the procedure is a bit more cumberstone: open the so-called 'Class expression editor' and use OR to separate the concepts you want to list there.
All best,
--ale
Following ontology engineering good practices, the domain of properties that have skos:Concept
as range can be detailed (they are empty right now)
ePO-Restrictions:
<owl:cardinality>
: some properties have Cardinality written the C upper case: <owl:Cardinality>
. This is an error of the script as it should be in lower case.
Some restrictions do not have “restrictions”, which creates an error when opening the file. They should have a restriction, such as the cardinality or hasValue:An example of "empty" restrictions:
<owl:Class rdf:about="http://data.europa.eu/a4g/ontology#EvaluationBoard">
<rdfs:subClassOf>
<owl:Restriction>
<owl:onProperty rdf:resource="http://data.europa.eu/a4g/ontology#isAssignedForEvaluationOf"/>
</owl:Restriction>
</rdfs:subClassOf>
</owl:Class>
currently dc is defined like so
xmlns:dc="http://www.omg.org/spec/UML/20131001/UMLDC"
we need it to be defined like so
xmlns:dc="http://purl.org/dc/elements/1.1/"
In the OWL restriction file (version at 13 November), all the CEFACT classes are repeated: one occurrence is written in first letter upper case, the second occurrence is written in lower case with no annotations or restrictions at all defined.
Examples:
ePO_restrictions.ttl has 66 occurrences of <skos:Concept>
, eg
epo:appliesRemedyType rdfs:range <skos:Concept> .
Please note that <skos:Concept>
is a CURIE using the undefined/invalid scheme skos:
,
rather than the prefixed URL skos:Concept
.
This is a serious mistake. Luckily it's the only one of this kind, as can be checked with
grep -P '<(?!http|/?u>|/?b>)' *.ttl | less
Make sure the current generation of node shapes with constraints on properties is correctly generated.
consider this comment from Ivo:
[18:37] VELITCHKOV Ivo (DIGIT-EXT)
costezki.eugen (Guest)you know, whatever you find, can you please report them on the GitHub issues?
Basically, I believe that intention was not to make a node shape but a property shape and target the objectsof the ePo property. Or:
:hasAdditionalContractNature-inScheme
rdf:type sh:PropertyShape ;
sh:path skos:inScheme ;
sh:hasValue atold:Contract-nature ;
sh:targetObjectsOf epo:hasAdditionalContractNature ;
.
[18:38] VELITCHKOV Ivo (DIGIT-EXT)
With this I'm also making another recommendation: never to use blank nodes in SHACL (I know the spec is written like that for readability but in practice that's always problematic and reduces modularity)
[18:38] VELITCHKOV Ivo (DIGIT-EXT)
If I find time I'll put some issues but I wanted just to share something I spotted now
[18:42] VELITCHKOV Ivo (DIGIT-EXT)
Depending on the orginal intention, there are four other solutions, for example
sh:path (
epo:hasAdditionalContractNature
skos:inScheme
) ;
[18:43] VELITCHKOV Ivo (DIGIT-EXT)
But in all cases, the current shape will look in the wrong nodes to check that the right reference data is used.
like 1
I think that the capitalization of cefact:code in the range
statement is wrong because the class is spelled Capitalized:
epo:eSubmissionPermission
a owl:FunctionalProperty ;
rdfs:domain epo:SubmissionTerm ;
rdfs:range <http://www.unece.org/cefact#code> .
<http://www.unece.org/cefact#Code>
a owl:Class ;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.