jetbrains / xodus-dnq Goto Github PK
View Code? Open in Web Editor NEWData definition and queries Kotlin DSL over Xodus
License: Apache License 2.0
Data definition and queries Kotlin DSL over Xodus
License: Apache License 2.0
I wanted to use the current version of Kotlin with Xodus (JetBrains/xodus#17). I can't see a way to install a local snapshot of xodus-dnq. Is there a way to do this?
./gradlew clean install
reports that task install
is unavailable.
Currently the number of proxy BasePersistentClassImpl instances is really huge for apps reusing same XdModel for lots of EntityStore instancds
I couldn't find a way to load an XdEntity by EntityId (a string with a value of an EntityId).
I guess that there's a better way, but here's my code to to this:
import kotlinx.dnq.XdEntity
import kotlinx.dnq.XdNaturalEntityType
open class XdCustomEntityType<T : XdEntity>() : XdNaturalEntityType<T>(storeContainer = ThreadLocalStoreContainer) {
fun find(id: String): T? {
val transaction = (XdOrganisation.entityStore.threadSession
?: throw IllegalStateException("New entities can be created only in transactional block"))
val entity = transaction.getEntity(transaction.toEntityId(id))
return wrap(entity).apply {
constructor()
}
}
}
When XdModel#toXd
is run it uses reflection to get the entityConstructor
. The result may be cached.
To reduce allocations and gc pressure on wrap operations
Here is the case:
class Group(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Group>() {
fun new() = new {
this.resource = Resource.new()
}
}
var resource by xdLink1(Resource, onDelete = OnDeletePolicy.CASCADE, onTargetDelete = OnDeletePolicy.FAIL)
override fun beforeFlush() {
super.beforeFlush()
if (hasChanges(Group::resource) && getOldValue(Group::resource) != null) {
throw RuntimeException("Can't change resource")
}
}
}
class Service(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Service>() {
val instance by xdSingleton()
}
val resources by xdChildren0_N(Resource::service)
}
class Resource(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<Resource>() {
fun new() = new {
this.service = Service.instance
}
}
var service: Service by xdParent(Service::resources)
}
class TestCase {
@Test
fun `should throw on changing resource`() {
XdModel.registerNodes(Group, Resource, Service)
val dir = Files.createTempDirectory("xodus")
val store = StaticStoreContainer.init(dir.toFile(), "test")
initMetaData(XdModel.hierarchy, store)
val group1 = store.transactional { Group.new() }
val group2 = store.transactional { Group.new() }
assertThrows<RuntimeException> {
store.transactional {
group1.resource.delete()
group1.resource = group2.resource
}
}
}
}
The exceptions is never thrown in this case as there is no old value for the resource
property. As for the changes tracker, here is what it contains on the moment of the beforeFlush
execution:
The example above works as expected if I put the explicit resource deletion after the assignment:
group1.resource = group2.resource
group1.resource.delete()
xodus-dnq
seems to be incompatible with Java 16.
I can't really tell how much of it does not work with Java 16, because it already breaks when calling initMetaData
- because that call leads to the usage of javassist.util.proxy.ProxyFactory
which is using some illegal reflection.
Here is the stack trace which comes up when calling
initMetaData(XdModel.hierarchy, store)
Exception in thread "main" java.lang.ExceptionInInitializerError
at javassist.util.proxy.DefineClassHelper.<clinit>(DefineClassHelper.java:216)
at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:128)
at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:552)
at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:475)
at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:444)
at javassist.util.proxy.ProxyFactory.create(ProxyFactory.java:721)
at kotlinx.dnq.util.XdHierarchyNode$naturalPersistentClassInstance$2.invoke(XdHierarchyNode.kt:96)
at kotlinx.dnq.util.XdHierarchyNode$naturalPersistentClassInstance$2.invoke(XdHierarchyNode.kt:33)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at kotlinx.dnq.util.XdHierarchyNode.getNaturalPersistentClassInstance(XdHierarchyNode.kt)
at kotlinx.dnq.util.DNQMetaDataUtilKt.initMetaData(DNQMetaDataUtil.kt:46)
at net.axay.pacmc.storage.Xodus.<clinit>(Xodus.kt:28)
at net.axay.pacmc.commands.Init$run$1.invokeSuspend(Init.kt:27)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @391ad520
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:357)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at javassist.util.proxy.SecurityActions$3.run(SecurityActions.java:94)
at javassist.util.proxy.SecurityActions$3.run(SecurityActions.java:90)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:554)
at javassist.util.proxy.SecurityActions.getMethodHandle(SecurityActions.java:89)
at javassist.util.proxy.DefineClassHelper$SecuredPrivileged$2.getDefineClassMethodHandle(DefineClassHelper.java:143)
at javassist.util.proxy.DefineClassHelper$SecuredPrivileged$2.<init>(DefineClassHelper.java:136)
at javassist.util.proxy.DefineClassHelper$SecuredPrivileged.<clinit>(DefineClassHelper.java:134)
... 19 more
Version of xodus-dnq I used is: 1.4.480
Could you mention the research papers this KV store is implementing ? Are there data structures and algorithms you found useful for this implementation ?
pls add
thanks
I've noticed that properties with unique = true
are not enforcing the uniqueness. See the program below which demonstrates this.
The program should fail to create an entity with a duplicate value of the unique property. It should also fail to create an empty property of the xdRequiredStringProp
, I think.
I'm using these version:
ext.xodus_version = '1.2.3358'
ext.xodus_dnq_version = '1.1.363'
Let me know if I misunderstood the API.
package myPackage
import jetbrains.exodus.entitystore.Entity
import kotlinx.dnq.XdEntity
import kotlinx.dnq.XdModel
import kotlinx.dnq.XdNaturalEntityType
import kotlinx.dnq.query.toList
import kotlinx.dnq.store.container.StaticStoreContainer
import kotlinx.dnq.xdRequiredStringProp
import java.io.File
class TestEntity(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<TestEntity>()
var uniqueName by xdRequiredStringProp(unique = true)
}
fun main(args: Array<String>) {
XdModel.registerNode(TestEntity)
val dir = File("test_entity_store")
if (dir.exists()) {
dir.deleteRecursively()
}
val store = StaticStoreContainer.init(dir, "db")
store.transactional {
TestEntity.new {
uniqueName = "value"
}
}
// expected that this transaction fails
store.transactional {
TestEntity.new {
uniqueName = "value"
}
}
// expected that this transaction fails due to the empty string (treated as null as described by xdRequiredStringProp)
store.transactional {
TestEntity.new {
uniqueName = ""
}
}
val names = store.transactional(readonly = true){
TestEntity.all().toList().map { it.uniqueName }
}
// prints "value, value, "
println(names)
}
I'm getting this exception when I run the test program below. Afaik this should throw a EntityRemovedInDatabaseException
. At least this is what jetbrains.exodus.entitystore.StoreTransaction#getEntity
has in the docs.
Ids in the form generated by Xodus can always be entered by users or send by external services.
As always, I'm sorry if I misunderstood the API...
Exception:
Exception in thread "main" jetbrains.exodus.env.ReadonlyTransactionException: Can't create a store in read-only transaction
at jetbrains.exodus.env.EnvironmentImpl.throwIfReadonly(EnvironmentImpl.java:904)
at jetbrains.exodus.env.EnvironmentImpl.openStoreImpl(EnvironmentImpl.java:784)
at jetbrains.exodus.env.EnvironmentImpl.openStore(EnvironmentImpl.java:191)
at jetbrains.exodus.env.EnvironmentImpl.openStore(EnvironmentImpl.java:51)
at jetbrains.exodus.entitystore.tables.SingleColumnTable.<init>(SingleColumnTable.java:33)
at jetbrains.exodus.entitystore.PersistentEntityStoreImpl$2$2.createTable(PersistentEntityStoreImpl.java:248)
at jetbrains.exodus.entitystore.OpenTablesCache.get(OpenTablesCache.java:45)
at jetbrains.exodus.entitystore.PersistentEntityStoreImpl.getEntitiesTable(PersistentEntityStoreImpl.java:1842)
at jetbrains.exodus.entitystore.PersistentEntityStoreImpl.getLastVersion(PersistentEntityStoreImpl.java:1488)
at jetbrains.exodus.entitystore.PersistentStoreTransaction.getEntity(PersistentStoreTransaction.java:276)
at com.jetbrains.teamsys.dnq.database.TransientSessionImpl.getEntity(TransientSessionImpl.kt:257)
at kotlinx.dnq.util.IdsKt.findById(Ids.kt:27)
at com.logrally.server.TestKt$main$1.invoke(test.kt:27)
at com.logrally.server.TestKt$main$1.invoke(test.kt)
at com.jetbrains.teamsys.dnq.database.TransientEntityStoreExt.transactional(TransientEntityStoreExt.kt:51)
at com.jetbrains.teamsys.dnq.database.TransientEntityStoreImpl.transactional(TransientEntityStoreImpl.kt:95)
at jetbrains.exodus.database.TransientEntityStore$DefaultImpls.transactional$default(TransientEntityStore.kt:84)
at com.logrally.server.TestKt.main(test.kt:26)
Code:
package com.logrally.server
import jetbrains.exodus.entitystore.Entity
import kotlinx.dnq.XdEntity
import kotlinx.dnq.XdModel
import kotlinx.dnq.XdNaturalEntityType
import kotlinx.dnq.store.container.StaticStoreContainer
import kotlinx.dnq.util.findById
import kotlinx.dnq.util.initMetaData
import java.io.File
class TestEntity(entity: Entity) : XdEntity(entity) {
companion object : XdNaturalEntityType<TestEntity>()
}
fun main(args: Array<String>) {
XdModel.registerNode(TestEntity)
val dir = File("test_entity_store")
if (dir.exists()) {
dir.deleteRecursively()
}
val store = StaticStoreContainer.init(dir, "db")
initMetaData(XdModel.hierarchy, store)
store.transactional {
TestEntity.findById("42-42")
}
}
I can't find any documentation about or example of changing definitions for data and migrating old data to it. Would you create a new class and migrate the data in the application with no direct support from xodus-dnq? Would you have to move everything linked to new definitions as well?
Now it's possible to do per JVM only
The following test code fails.
val root = store.transactional { RootGroup.new { name = "root group 1" } }
val nested = store.transactional {
NestedGroup.new {
name = "nested"
owner = User.new { login = "owner"; skill = 1 }
parentGroup = root
}
}
store.transactional {
assertThat(nested.getOldValue(NestedGroup::parentGroup)).isEqualTo(root)
}
It's not possible to use the current version of the project.
Could you release all the needed components?
> Could not find org.jetbrains.xodus:xodus-query:1.2.3217.
Searched in the following locations:
- https://jcenter.bintray.com/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.pom
- https://jcenter.bintray.com/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.jar
- http://kotlin.bintray.com/ktor/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.pom
- http://kotlin.bintray.com/ktor/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.jar
- https://dl.bintray.com/kotlin/kotlin-eap/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.pom
- https://dl.bintray.com/kotlin/kotlin-eap/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.jar
- https://repo.maven.apache.org/maven2/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.pom
- https://repo.maven.apache.org/maven2/org/jetbrains/xodus/xodus-query/1.2.3217/xodus-query-1.2.3217.jar
Required by:
project : > org.jetbrains.xodus:dnq:1.1.363
project : > org.jetbrains.xodus:dnq:1.1.363 > org.jetbrains.xodus:dnq-open-api:1.1.363
> Could not find org.jetbrains.xodus:xodus-utils:1.2.3217.
Thus there is an ability to create an instance of abstract type in database. See this issue.
I would like to store Metadata from external sources in Xodus by using dnq. Me is pretty new to both, so I do appreciate any feedback.
Since the Data is from external sources, I do know some of the fields I need to store, but not all. Therefore I want to store those additional properties as a Map on the entity. Is this possible using dnq?
I was thinking along the lines of a link to a generic entity, but then I am unable to use dnq to fetch this entity using dnq.
Hey,
I attempted to embed Xodus and, of course, Xodus DNQ into a Spring project, and turn it into a native executable via GraalVM/Spring Native. Using the latest version of DNQ in Maven Central (1.4.480
), I was unable to do so, because of how initMetaData
is implemented.
However, by using the GitHub HEAD, which contains this crucial change: 915882d#diff-4ad8a6eb500db387708f3c0bf45d4005c4bd9f8e81463ef793424a8a678667fdL46 (and the removal of javassist
, of course), I could get Xodus DNQ up & running with Spring Native.
Currently, my project depends on hand-built DNQ JARs, but it'd be much better to obtain them from Maven Central. Therefore, I wanted to ask, whether you plan on releasing a new version in the future, and if so, then when exactly?
Best regards,
Attila
Thanks for adding entityId
/ xdId
!
Is there a way to create a NodeBase
query to locate by entityId
? This would be useful to have generic, user-defined queries.
I currently store xdId in a property of type String, but that's inefficient.
Otherwise, sorting over the result of the union/plus returns incomplete iterable. Such a sort returns items of the left part of the union/plus. It happens because the result of the union/plus inherits the entityType
of the left part. When the result is passed into the queryEngine
to sort over a property the engine returns only the entities of the passed entity type.
I was quite surprised to see entityIterable with nulls:
interface XdQuery<out T : XdEntity> {
val entityType: XdEntityType<T>
val entityIterable: Iterable<Entity?>
}
To see where the problem is let's consider the simplest use case
XdProject.all().entityIterable // Iterable<Entity?>
What does it mean? Why are there nulls among my projects? It just doesn't make sense.
Where Iterable<Entity?> does make sense is in map/distinctMap, and even there nullability should be inferred from a closure return type.
To make the matters worse naive developer is likely to use kotlin collection API to get rid of nulls:
XdUser.all().entityIterable.filterNotNull() // whoops, 200 000 users are now in memory
I've added the example from documentation and tried to build, but there is an error:
e: /<my_path>/app/build/tmp/kapt3/stubs/main/my/app/package/db/xodus/XdGender.java:31: error: as of release 5, 'enum' is a keyword, and may not be used as an identifier public static final class Companion extends kotlinx.dnq.enum.XdEnumEntityType<my.app.package.db.xodus.XdGender> {
As I understand XdEnumEntityType is located in kotlinx.dnq.enum, but we cannot use enum in java code. Please help me fix this issue.
QueryOperations.reverse is ported to xodus-dnq extension function for XdQuery. See this commit with muted test.
As a result, cancelling policy doesn't work for any TransientSession that accumulates write changes.
I'm interested to use the dnq library with xodus (I'm new to both).
I found out that I have to add maven { url 'http://repository.jetbrains.com/xodus' }
to make the dependencies resolve.
https://repo.maven.apache.org/maven2/org/jetbrains/xodus/dnq-open-api/1.1.226/dnq-open-api-1.1.226.pom uses Xodus 1.0.2766
, the latest public release is 1.1.0
(https://github.com/JetBrains/xodus).
Which version of Xodus should I use?
Is there a version of xodus-dnq which uses the 1.1.0 release?
Thanks a lot!
I've encountered some bizarre exception that crashes the whole app on calling XdModel.registerNodes
Stack trace:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at kotlinx.dnq.util.ReflectionUtilKt$entityConstructor$1.invoke(ReflectionUtil.kt:75)
at kotlinx.dnq.util.ReflectionUtilKt$entityConstructor$1.invoke(ReflectionUtil.kt)
at kotlinx.dnq.util.XdHierarchyNode.<init>(XdHierarchyNode.kt:72)
at kotlinx.dnq.XdModel.registerNode(XdModel.kt:106)
at kotlinx.dnq.XdModel.registerNodes(XdModel.kt:139)
at by.enrollie.xodus.InitializeDBKt.initializeDB(InitializeDB.kt:18)
at by.enrollie.xodus.DatabaseProviderImplementation.<init>(DatabaseProviderImplementation.kt:15)
at MainKt.main(main.kt:11)
at MainKt.main(main.kt)
Caused by: java.lang.ClassCastException: class kotlinx.dnq.util.FakeEntity cannot be cast to class jetbrains.exodus.database.TransientEntity (kotlinx.dnq.util.FakeEntity and jetbrains.exodus.database.TransientEntity are in unnamed module of loader 'app')
at com.jetbrains.teamsys.dnq.database.TransientEntityUtilKt.reattachTransient(TransientEntityUtil.kt:37)
at kotlinx.dnq.util.TransientEntityUtilKt.reattach(TransientEntityUtil.kt:29)
at kotlinx.dnq.util.TransientEntityUtilKt.reattach$default(TransientEntityUtil.kt:29)
at kotlinx.dnq.util.TransientEntityUtilKt.reattachAndGetPrimitiveValue(TransientEntityUtil.kt:35)
at kotlinx.dnq.simple.XdProperty.getValue(XdProperty.kt:43)
at kotlinx.dnq.simple.XdProperty.getValue(XdProperty.kt:27)
at kotlinx.dnq.simple.XdWrappedProperty.getValue(XdWrappedProperty.kt:39)
at by.enrollie.xodus.classes.XdRole.getGranted(XdRole.kt:36)
at by.enrollie.xodus.classes.XdRole$revoked$2$1.invoke(XdRole.kt:37)
at by.enrollie.xodus.classes.XdRole$revoked$2$1.invoke(XdRole.kt:37)
at kotlinx.dnq.simple.PropertyConstraintsKt.isAfter$default(PropertyConstraints.kt:491)
at by.enrollie.xodus.classes.XdRole$revoked$2.invoke(XdRole.kt:37)
at by.enrollie.xodus.classes.XdRole$revoked$2.invoke(XdRole.kt:37)
at kotlinx.dnq.simple.FactoriesKt.collect(Factories.kt:34)
at kotlinx.dnq.PropertyDelegatesKt$xdDateTimeProp$1.invoke(PropertyDelegates.kt:639)
at kotlinx.dnq.PropertyDelegatesKt$xdDateTimeProp$1.invoke(PropertyDelegates.kt)
at kotlinx.dnq.util.XdPropertyCachedProvider.provideDelegate(XdPropertyCachedProvider.kt:41)
at by.enrollie.xodus.classes.XdRole.<init>(XdRole.kt:37)
... 14 more
Source code of an app: https://github.com/enrollie/Eversity-XodusDB
For example
let us have type XdFoo
with property bar
: Long
Expression XdFoo.filter(XdFoo::bar lt 20) should not be compiled or at least throw an exception in runtime.
Dear Xodus-DNQ Maintainers,
Thank you for this awesome lib.
I've learned that string property values are case-insensitive in Xodus (according to the wiki).
Hence, with the following entity:
XdMyEntity(entity: Entity) : XdEntity(entity) {
var name by xdRequiredStringProp()
}
and the following query:
val xdEntities = XdMyEntity.query(
XdMyEntity::name eq "focusable"
).toList()
for (xdMyEntity in xdEntities) {
println(xdMyEntity.name)
}
Suppose that I have two entities with names: "focusable" and "FOCUSABLE"
Then the above query will print both names:
FOCUSABLE
focusable
I was wondering if DNQ has a convenience method to do case-sensitive queries. If not, is it best just to filter the query results with normal kotlin collection operations? In any case, thank you for open sourcing this lib!
Warm regards,
Derk
queryEngine.selectDistinct can return collection with null values inside but XdQuery treated all values inside as not-null therefore iterating of XdQuery will fail.
As I see there are few possibilities to fix it:
(I'm sorry to posting here instead of Stackoverflow. I'm new on Stackoverflow and couldn't send the post because the tag Xodus-DNQ wasn't created yet and I can't to this as a new user)
I'm new to Xodus and Xodus-DNQ.
I'd like to create more than one store container in the same application. The reason is that I'd like to have separate data containers for different sets of users.
The transaction handling seems to be confused after the 2nd store was created.
My current understanding is that XdModel is a singleton and using it I don't see a way to have to data stores.
Is there another way to create/init/manager two or more data stores at the same time?
Exception for store1.transactional { ... }
:
Exception in thread "main" java.lang.IllegalStateException: New entities can
created only in transactional block
at kotlinx.dnq.XdEntityType.new(XdEntityType.kt:35)
The sample code I used:
val store1 = StaticStoreContainer.init(dbFolder = File("/home/user/tmp/repo1"), environmentName = "repo1")
XdModel.registerNodes(XdContact)
initMetaData(XdModel.hierarchy, store1)
val store2 = StaticStoreContainer.init(dbFolder = File("/home/user/tmp/repo2"), environmentName = "repo1")
XdModel.registerNodes(XdContact)
initMetaData(XdModel.hierarchy, store2)
store1.transactional {
XdContact.new {
this.email="[email protected]"
this.firstname="First"
this.lastname="Last"
}
}
store2.transactional {
XdContact.new {
this.email="[email protected]"
this.firstname="First"
this.lastname="Last"
}
}
Using:
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.