samvera-labs / fedora-migrate Goto Github PK
View Code? Open in Web Editor NEWGem for migrating content to Fedora4
License: Other
Gem for migrating content to Fedora4
License: Other
If you follow the instructions in the 'Usage' portion of the README and only include the namespace parameter in the call to FedoraMigrate.migrate_repository, the options instance variable ends up being nil in FedoraMigrate::RepositoryMigrator and causes an error at https://github.com/projecthydra-labs/fedora-migrate/blob/master/lib/fedora_migrate/repository_migrator.rb#L13 .
2.1.5 :002 > FedoraMigrate.migrate_repository(namespace: "changeme")
NoMethodError: undefined method `fetch' for nil:NilClass
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora_migrate/repository_migrator.rb:13:in `initialize'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:53:in `new'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:53:in `migrate_repository'
from (irb):2
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/console.rb:90:in `start'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/console.rb:9:in `start'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/commands_tasks.rb:69:in `console'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands.rb:17:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Currently, we're just dumping out a list in JSON. We could log successes and failures, allowing a re-run that only migrates the objects that failed.
Sufia's label method needs to be migrated to the Fedora 4's label property fedorasystem:downloadFilename
This question was brought up in samvera-deprecated/curation_concerns#716
The scenarios are:
The original intention of the gem was just the first scenario. Whether or not it would hold up with the other two is unknown. We could build a new gem just for PCDM migrations, which would leave this gem only responsible for migrating Sufia from 5 to 6, then the new gem does 6 to 7.
Ping: @mjgiarlo @barmintor @hectorcorrea, who's currently working on some PCDM migration tools for Penn State.
Use a version of CurationConcerns >= 1.0.0.beta1, < 2
This will pull in HydraHead >= 10.0.0.beta1, < 11
RELS-INT datastreams can be migrated in a similar way that RELS-EXT is.
When migrating RDF datastreams, this error can appear:
Ldp::BadRequest: java.text.ParseException: Next event is not a Separator
While not relevant for Hydra applications, migrating and converting DC datastreams to RDF would be a valuable feature..
In certain cases, Fedora will add
<?xml version="1.0">
to the beginning of xml files if it is not present in the source. While this doesn't affect the validity of the xml data, it does break the checksum verification, so we have no way of knowing for sure if the migrated content is the same as the source.
Verification with the equivalent_xml gem would solve this.
When migrating datastreams, the date the content was originally created ought to be preserved somehow. The created
attribute will be the date the resource was created in real time, but this would be the time when it was actually migrated. We need to retain the date when the resource was created back when it was in Fedora3.
As I understand it, the 'get_config_path' method used to be present in AF::FileConfigurator but is not as 9.6.2.
2.1.5 :001 > FedoraMigrate.migrate_repository(namespace: "changeme", options: { convert: "descMetadata" })
NoMethodError: undefined method `get_config_path' for #<FedoraMigrate::FileConfigurator:0x007fc65ba03768>
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora_migrate/file_configurator.rb:11:in `load_fedora3_config'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora_migrate/file_configurator.rb:5:in `fedora3_config'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:41:in `fedora_config'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:45:in `source'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora_migrate/repository_migrator.rb:29:in `get_source_objects'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora_migrate/repository_migrator.rb:14:in `initialize'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:53:in `new'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/fedora-migrate-0.2.0/lib/fedora-migrate.rb:53:in `migrate_repository'
from (irb):1
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/console.rb:90:in `start'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/console.rb:9:in `start'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/commands_tasks.rb:69:in `console'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
from /Users/coblej/.rvm/gems/ruby-2.1.5@dul-hydra-f4/gems/railties-4.1.13/lib/rails/commands.rb:17:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
CircleCI can be used to prevent the recreation of the old default branch name. This helps preserve automatic redirection to the new default branch, and prevents accidentally re-adding the legacy branch from a stale fork. If CircleCI is not integrated with this repository, please do the following:
Add information to the README explicitly defining branch naming conventions accepted for this repository (instructions in this GitHub gist).
Optionally, integrate CircleCI with your repository (see GitHub documentation from CircleCI), and add a test to fail when a branch called master
is present (instructions in this GitHub gist).
Git's default "master" branch derives from "master/slave" jargon which perpetuates systemic racist language and systems (see email Replacing "master" reference in git branch names). To uphold our Code of Conduct, we must move away from the term "master" in our technical language (as well as words like blacklist or whitelist).
When objects encountered in the RELS-EXT are missing, the relationship migration fails because Fedora 4 enforces strong relationships. However, if the objects are indeed missing in the source Fedora 3 repo, should you re-create the objects? This would then make the migrated repository not a true reflection of the source repo.
Another option could be to create the objects in Fedora 4, then delete them and leave their tombstones. This should enforce Fedora 4's strong relationships, but reflect the true status of the source data since the original objects were missing to begin with.
The Renaming Branch Working Group is in the process of renaming the default branch from master
to main
in Samvera and Samvera-Labs repos. This brings repositories into compliance with the Samvera Community Code of Conduct (https://samvera.atlassian.net/wiki/spaces/samvera/pages/405212316/Code+of+Conduct) and language recommendations (https://github.com/samvera/maintenance/blob/master/templates/CONTRIBUTING.md#language).
This issue will be complete when the master
has been renamed to main
.
Related issues will have a title beginning with RENAME
.
You can specify a datastream in the target object, but if that datastream doesn't exist in the source you'lll get a NoMethodError on verify
.
This repository’s default branch has already been renamed using GitHub’s renaming tool. Links that reference the old branch name are automatically forwarded to the new default branch. But string references are not automatically updated.
Check this repository for hard-coded string references to the legacy “master” default branch and update them to the new default branch name “main.”
Important places to check include, but are not limited to:
NOTE: READMEs, wikis, and other documentation are important to update to avoid confusion and correct errors in long lasting documentation.
Less common places to check:
NOTE: String references to themaster
branch in Issues, PRs, and code are uncommon. Also Issues and PRs are temporal in nature, making it less critical to update those occurrences.
Git's default "master" branch derives from "master/slave" jargon which perpetuates systemic racist language and systems (see email Replacing "master" reference in git branch names). To uphold our Code of Conduct, we must move away from the term "master" in our technical language (as well as words like blacklist or whitelist).
FCR3 DS Labels aren't guaranteed to have any kind of useful ds label. Should this method reproduce the FCR3 logic of deciding how to set the Content-Disposition header, or just be configurable?
RDF conversion only works with RDF::DC terms. We need to fix that.
The code used for migrating relationships is problematic and needs some refactoring and deeper testing.
This item in Fedora3 has this description:
https://scholarsphere.psu.edu/files/7d279232g#.VMfeyHDF_iE
When converted, it displays as:
https://scholarsphere-qa.dlt.psu.edu/files/7d279232g#.VMfetXDF_iE
I'm working on a fork that would allow registration of Mover classes for content migrations by attached_file name, and wanted to open a conversation here. The idea is that, for a target class that (<>ldp:contains 'foo','bar'), the ObjectMover has a map (defaulting to DatastreamMover) of Mover impls that might perform some arbitrary action for the migration of that content. For example, it may go grab the contents for 'foo' from another object that won't be migrated, or just insert default content.
When the datastream being migrated is greater than 2 GB in size, an exception is thrown during the execution of 'save' in FedoraMigrate::ContentMover#move_content ( https://github.com/projecthydra-labs/fedora-migrate/blob/master/lib/fedora_migrate/content_mover.rb#L28 ). The stack trace is shown below. We think that this may be due to the fact that the content of the source datastream is being assigned as a string to the target attached_file content ( https://github.com/projecthydra-labs/fedora-migrate/blob/master/lib/fedora_migrate/content_mover.rb#L25 ) and could perhaps be addressed by wrapping the source content in an IO object.
Exception
RangeError
Error
integer 2185175220 too big to convert to `int'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/openssl/buffering.rb:326:in `syswrite'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/openssl/buffering.rb:326:in `do_write'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/openssl/buffering.rb:344:in `write'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/protocol.rb:211:in `write0'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/protocol.rb:185:in `block in write'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/protocol.rb:202:in `writing'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/protocol.rb:184:in `write'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http/generic_request.rb:184:in `send_request_with_body'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http/generic_request.rb:130:in `exec'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1412:in `block in transport_request'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1411:in `catch'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1411:in `transport_request'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1384:in `request'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1377:in `block in request'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:853:in `start'
/home/hydra/.rvm/rubies/ruby-2.1.8/lib/ruby/2.1.0/net/http.rb:1375:in `request'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:82:in `perform_request'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:40:in `block in call'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:87:in `with_net_http_connection'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:32:in `call'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/request/url_encoded.rb:15:in `call'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:in `build_response'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in `run_request'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/faraday-0.9.2/lib/faraday/connection.rb:177:in `put'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/ldp-0.4.1/lib/ldp/client/methods.rb:92:in `block in put'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications.rb:161:in `instrument'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/ldp-0.4.1/lib/ldp/client/methods.rb:90:in `put'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/caching_connection.rb:24:in `put'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/ldp-0.4.1/lib/ldp/resource.rb:72:in `create'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/file.rb:232:in `block (2 levels) in create_record'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:82:in `run_callbacks'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/file.rb:229:in `block in create_record'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/callbacks.rb:82:in `run_callbacks'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/file.rb:228:in `create_record'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/persistence.rb:141:in `create_or_update'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/active-fedora-9.8.2/lib/active_fedora/persistence.rb:27:in `save'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/mover.rb:28:in `save'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/content_mover.rb:28:in `move_content'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/content_mover.rb:14:in `migrate'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/datastream_mover.rb:54:in `migrate_content'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/datastream_mover.rb:40:in `migrate_current'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/datastream_mover.rb:34:in `migrate_datastream'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/datastream_mover.rb:23:in `migrate'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/object_mover.rb:59:in `block in migrate_content_datastreams'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/object_mover.rb:57:in `each'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/object_mover.rb:57:in `migrate_content_datastreams'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/object_mover.rb:47:in `migrate_datastreams'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/bundler/gems/fedora-migrate-757504b6443b/lib/fedora_migrate/object_mover.rb:12:in `migrate'
/srv/perkins/hydra/dul-hydra/lib/dul_hydra/migration/migrate_single_object_job.rb:26:in `block in migrate'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `block in instrument'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `instrument'
/srv/perkins/hydra/dul-hydra/lib/dul_hydra/migration/migrate_single_object_job.rb:22:in `migrate'
/srv/perkins/hydra/dul-hydra/lib/dul_hydra/migration/migrate_single_object_job.rb:13:in `block in perform'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `block in instrument'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/home/hydra/.rvm/gems/ruby-2.1.8@dul-hydra/gems/activesupport-4.1.14/lib/active_support/notifications.rb:159:in `instrument'
/srv/perkins/hydra/dul-hydra/lib/dul_hydra/migration/migrate_single_object_job.rb:10:in `perform'
The maintenance template for CONTRIBUTING.md is used by all Samvera repos. Replace the current version with the updated maintenance template version.
Certain characters in the subject of a triple are causing RDF::Reader to fail. This happens during RDF datastream conversion, usually in the description field.
Add the following branch renaming language to the README for this repository.
## Contributing
If you're working on PR for this project, create a feature branch off of `main`.
This repository follows the [Samvera Community Code of Conduct](https://samvera.atlassian.net/wiki/spaces/samvera/pages/405212316/Code+of+Conduct) and [language recommendations](https://github.com/samvera/maintenance/blob/master/templates/CONTRIBUTING.md#language). Please ***do not*** create a branch called `master` for this repository or as part of your pull request; the branch will either need to be removed or renamed before it can be considered for inclusion in the code base and history of this repository.
Git's default "master" branch derives from "master/slave" jargon which perpetuates systemic racist language and systems (see email Replacing "master" reference in git branch names). To uphold our Code of Conduct, we must move away from the term "master" in our technical language (as well as words like blacklist or whitelist).
If you list more than one RDF datastream as a convert
option, only the attributes from the first RDF datastream are actually persisted to the target object.
The order in which datastreams are migrated to new objects should be configurable. This allows required fields to be set before the object is saved.
This doesn't apply in cases where descMetadata is converted to RDF, as in Sufia's migration, but we should offer this option for non-Sufia heads.
Stop using the migrate fork of jettywrapper, and use the fcrepo_wrapper gem to handle Fedora 4 downloads. We'll still need to use jettywrapper for Fedora 3, but at least we can stick to released versions instead of forks. The solr that comes with jettywrapper should continue to work for our needs.
Use Case:
I want to migrate my Fedora 3 objects, but I don't want to use the PID that comes with them.
Examples:
Using Fedora's own minting setup
Given Fedora 3 object namespace:1234
When I migrate this to Fedora
I want the Fedora 4 object to be the default UUID minted by the application
And I want the namespace:1234 pid to be searchable in a predicate on the migrated resource
Using some other minting scenario
Given Fedora 3 object namespace:1234
When I migrate this to Fedora
I want the Fedora 4 object to be /some/path/to/resource/12/34/xyz
And I want the namespace:1234 pid to be searchable in a predicate on the migrated resource
This is listed as a Hydra Labs project, covered under the Project Hydra CLA, but is released here under MIT. Can you clarify the license for this project?
Rubydora's search mechanism for returning all objects in the repository may default to only a limited number. We may need to "page" through these results in order to get to every object.
Currently, Fedora 4 does not have audit trail information that is present in the Fedora 3 object. If that feature is added to Fedora 4, we should consider that option of migrating it as well.
The migration of "content datastreams" is a "pull" operation based on the keys of the attached_files hash of the F4 target object. Just because a datastream is not defined in the AF model doesn't necessary mean it shouldn't be migrated.
Hi,
I am new to Fedora-Migrate. I would like to migrate existing fedora3 data to fedora 4. Regarding the following instructions, I have a question.
When the migrator finds an object in your Fedora3 repository that has the name MyModel it attempts >to instantiate the object MyModel in the context of your Hydra application.
I could not clearly find the data model in my fedora data. I believe it shall contains those standard fedora 3 models. How do I configure fedora-migrate gem to migrate those data models?
Thanks
Allow users to pass their own checksum method for datastream verification.
def has_matching_checksums?
checksum(datastream) == target_checksum
end
def checksum content
content.respond_to?(:checksum) ? content.checksum : Digest::SHA1.hexdigest(content)
end
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.