Merge branch 'master' into fusiontables-migration

Conflicts:
	.classpath
	extensions/gdata/module/MOD-INF/controller.js
	extensions/gdata/src/com/google/refine/extension/gdata/GDataImporter.java
This commit is contained in:
Tom Morris 2013-07-25 16:13:04 -04:00
commit 00dd7f2bdd
212 changed files with 5781 additions and 1474 deletions

View File

@ -13,7 +13,7 @@
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/arithcode-1.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/butterfly-trunk.jar" sourcepath="main/webapp/WEB-INF/lib-src/butterfly-trunk-sources.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/clojure-1.4.0.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-codec-1.5.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-codec-1.6.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-collections-3.2.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-fileupload-1.2.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-io-1.4.jar"/>
@ -42,7 +42,7 @@
<classpathentry exported="true" kind="lib" path="server/lib/jetty-6.1.22.jar" sourcepath="server/lib-src/jetty-6.1.22-sources.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/jetty-util-6.1.22.jar" sourcepath="server/lib-src/jetty-util-6.1.22-sources.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/log4j-1.2.15.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/servlet-api-2.5.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/servlet-api-2.5.jar" sourcepath="server/lib-src/servlet-api-2.5-sources.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/slf4j-api-1.5.6.jar"/>
<classpathentry exported="true" kind="lib" path="server/lib/slf4j-log4j12-1.5.6.jar"/>
<classpathentry exported="true" kind="lib" path="broker/appengine/WEB-INF/lib/slf4j-jdk14-1.5.6.jar"/>
@ -51,8 +51,8 @@
<classpathentry exported="true" kind="lib" path="extensions/gdata/module/MOD-INF/lib/gdata-core-1.0.jar"/>
<classpathentry exported="true" kind="lib" path="extensions/gdata/module/MOD-INF/lib/gdata-spreadsheet-3.0.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/jsoup-1.4.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/tests/server/lib/mockito-all-1.8.4.jar"/>
<classpathentry exported="true" kind="lib" path="main/tests/server/lib/testng-5.12.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/tests/server/lib/mockito-all-1.9.5.jar"/>
<classpathentry exported="true" kind="lib" path="main/tests/server/lib/testng-6.8.jar"/>
<classpathentry exported="true" kind="lib" path="extensions/gdata/module/MOD-INF/lib/gdata-docs-3.0.jar"/>
<classpathentry exported="true" kind="lib" path="extensions/gdata/module/MOD-INF/lib/gdata-docs-meta-3.0.jar"/>
<classpathentry exported="true" kind="lib" path="extensions/gdata/module/MOD-INF/lib/gdata-media-1.0.jar"/>
@ -66,8 +66,8 @@
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/serializer.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/xercesImpl-2.11.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/xml-apis.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/httpclient-4.1.2.jar" sourcepath="main/webapp/WEB-INF/lib-src/httpclient-4.1.2-sources.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/httpcore-4.1.3.jar" sourcepath="main/webapp/WEB-INF/lib-src/httpcore-4.1.3-sources.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/httpclient-4.2.5.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/httpcore-4.2.4.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/signpost-commonshttp4-1.2.1.2.jar" sourcepath="main/webapp/WEB-INF/lib-src/signpost-commonshttp4-1.2.1.2-sources.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/signpost-core-1.2.1.2.jar" sourcepath="main/webapp/WEB-INF/lib-src/signpost-core-1.2.1.2-sources.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/guava-13.0.jar"/>
@ -84,5 +84,8 @@
<classpathentry kind="lib" path="extensions/gdata/module/MOD-INF/lib/google-oauth-client-servlet-1.13.1-beta.jar"/>
<classpathentry kind="lib" path="extensions/gdata/module/MOD-INF/lib/guava-jdk5-13.0.jar"/>
<classpathentry kind="lib" path="extensions/gdata/module/MOD-INF/lib/jsr305-1.3.9.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/commons-logging-1.1.1.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/fluent-hc-4.2.5.jar"/>
<classpathentry exported="true" kind="lib" path="main/webapp/WEB-INF/lib/httpmime-4.2.5.jar"/>
<classpathentry kind="output" path="build"/>
</classpath>

1
.gitignore vendored
View File

@ -18,4 +18,5 @@ broker/core/module/MOD-INF/classes/
broker/core/WEB-INF/lib/
broker/core/data/
broker/core/test-output/
tmp/
/test-output

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="main/webapp/modules/core/MOD-INF/controller.js|main/webapp/modules/core/externals/|test-output/" kind="src" path=""/>
<classpathentry excluding="build/**|main/webapp/modules/core/MOD-INF/controller.js|main/webapp/modules/core/externals/|test-output/" kind="src" path=""/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path=""/>
</classpath>

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
language: java
jdk:
- oraclejdk7
- openjdk6
script: ./refine test

53
README.md Normal file
View File

@ -0,0 +1,53 @@
#OpenRefine
[![Build Status](https://travis-ci.org/OpenRefine/OpenRefine.png?branch=master)](https://travis-ci.org/OpenRefine/OpenRefine)
OpenRefine is a power tool that allows you to load data, understand it,
clean it up, reconcile it to master database, and augment it with data coming from
Freebase or other web sources. All with the comfort and privacy of
your own computer.
###Where can I get more information?
Look at the OpenRefine web site http://openrefine.org and the wiki http://github.com/OpenRefine/OpenRefine/wiki
###Licensing and legal issues
OpenRefine is open source software and is licensed under the BSD license
located in the [LICENSE.txt](LICENSE.txt). See that file also for information on open source
libraries that OpenRefine depends on.
###Credits
This software was created by Metaweb Technologies, Inc. and originally written
and conceived by David Huynh <dfhuynh@google.com>. Metaweb Technologies, Inc.
was acquired by Google, Inc. in July 2010 and the product was renamed Google Refine.
In October 2012, it was renamed OpenRefine as it transitioned to a
community-supported product.
This is the full list of contributors (in chronological order):
- David Huynh <dfhuynh@google.com>
- Stefano Mazzocchi <stefanom@google.com>
- Vishal Talwar <vtalwar@google.com>
- Jeff Fry <jfry@google.com>
- Will Moffat <wdm@google.com>
- James Home <jameshome@google.com>
- Iain Sproat <iainsproat@gmail.com>
- Tom Morris <tfmorris@gmail.com>
- Heather Campbell <campbellh@google.com>
- Thad Guidry <thadguidry@gmail.com>
- Paul Makepeace <paulm@paulm.com>
- Tomaž Šolc <tomaz.solc@zemanta.com>
- Gabriel Sjoberg <GabrielSjoberg@gmail.com>
- Rod Salazar <rodrod.salazar@gmail.com>
- pxb <pxb1988@gmail.com>
We welcome additional contributors if you'd like to help out.
Thank you for your interest.
----
The OpenRefine Development Team
http://openrefine.org

View File

@ -88,6 +88,9 @@
<path id="tests.class.path">
<path refid="webapp.class.path"/>
<path refid="server.class.path"/>
<pathelement location="${server.tests.classes.dir}"/>
<pathelement location="${server.tests.lib.dir}/testng-6.8.jar"/>
<fileset dir="${server.tests.lib.dir}">
<include name="**/*.jar" />
</fileset>
@ -136,7 +139,7 @@
<copy file="${webapp.src.dir}/log4j.properties" tofile="${webapp.classes.dir}/log4j.properties"/>
</target>
<target name="build_tests" depends="build_webapp, build_server">
<target name="build_tests" depends="build">
<mkdir dir="${server.tests.classes.dir}" />
<javac source="${java_version}" target="${java_version}" encoding="utf-8" srcdir="${server.tests.src.dir}" destdir="${server.tests.classes.dir}" debug="true" includeAntRuntime="no">
<classpath refid="tests.class.path" />
@ -168,6 +171,16 @@
<target name="build_broker" depends="build_broker_core, build_broker_appengine"/>
<taskdef resource="testngtasks" classpath="${server.tests.lib.dir}/testng-6.8.jar"/>
<mkdir dir="${build.dir}/server_tests"/>
<target name="server_test" depends="build_tests">
<testng workingdir="${build.dir}/server_tests"
listener="org.testng.reporters.DotTestListener" excludedgroups="broken"
classpathref="tests.class.path">
<xmlfileset file="${server.tests.dir}/conf/tests.xml"/>
</testng>
</target>
<!-- ================================================================== -->
<target name="prepare_jar">
@ -229,7 +242,7 @@
name="OpenRefine"
displayname="OpenRefine ${version}"
icon="${graphics.dir}/icon/openrefine.icns"
identifier="org.openrefine.refine.Refine"
identifier="com.google.refine.Refine"
shortversion="${version}"
mainclassname="com/google/refine/Refine">
<runtime dir="${env.JAVA_HOME}"/>
@ -241,8 +254,6 @@
</classpath>
<option value="-Xms256M"/>
<option value="-Xmx1024M"/>
<option value="-Djava.awt.headless=true"/>
<option value="-Drefine.headless=true"/>
<option value="-Drefine.version=${revision}"/>
<option value="-Drefine.webapp=$APP_ROOT/Contents/Resource/${built.webapp.name}"/>
</bundleapp>

View File

@ -57,7 +57,7 @@
<target name="build_java">
<mkdir dir="${classes.dir}" />
<javac encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<javac source="${java_version}" target="${java_version}" encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<src path="${src.dir}"/>
<classpath refid="class.path" />
</javac>

View File

@ -59,6 +59,7 @@ function init() {
RS.registerCommand(module, "import-qa-data", new Packages.com.google.refine.freebase.commands.ImportQADataCommand());
RS.registerCommand(module, "mqlread", new Packages.com.google.refine.freebase.commands.MQLReadCommand());
RS.registerCommand(module, "mqlwrite", new Packages.com.google.refine.freebase.commands.MQLWriteCommand());
RS.registerCommand(module, "load-language", new Packages.com.google.refine.freebase.commands.LoadLanguageCommand());
var OR = Packages.com.google.refine.operations.OperationRegistry;

View File

@ -0,0 +1,115 @@
{
"fb-schema-alignment": {
"close-confirm": "There are unsaved changes. Close anyway?",
"status-warning": "There are unsaved changes.",
"assert-link-found": "Assert link when 'true' is found in column",
"search-pick-property": "Search for a property or pick one below",
"search-property": "Search for a property",
"cell": "cell",
"cells": "cells",
"which-column": "Which column?",
"configure": "Configure...",
"which-topic": "Which topic?",
"what-value": "What value?",
"anonymous": "anonymous",
"add-property": "add property",
"anonymous-node": "Anonymous Node",
"freebase-topic": "Freebase Topic",
"value": "Value",
"skeleton-node": "Schema Alignment Skeleton Node",
"text": "text",
"int": "int",
"float": "float",
"double": "double",
"boolean": "boolean",
"date-time": "date/time",
"rawstring": "rawstring",
"set-to-cell": "Set to Cell in Column",
"cell-content-used": "The cell's content is used ...",
"specify-fb-topic": "to specify a Freebase topic, as reconciled",
"type-new-topics": "Type new topics as",
"literal-value": "as a literal value",
"literal-type": "Literal type",
"text-language": "Text language",
"key-namespace": "as a key in a namespace",
"namespace": "Namespace",
"generate-anonymous": "Generate an anonymous graph node",
"assign-type": "Assign a type to the node",
"use-existing-topic": "Use one existing Freebase topic",
"value-type": "Value type",
"language": "Language",
"use-literal-value": "Use a literal value",
"column-warning": "You must select at least one column",
"new-node-warning": "For creating a new graph node, you need to specify a type for it.",
"namespace-warning": "Please specify the namespace.",
"anonymous-node-warning": "For generating an anonymous graph node, you need to specify a type for it",
"specify-topic-warning": "Please specify which existing Freebase topic to use",
"specify-value-warning": "Please specify the value to use"
},
"fb-interface": {
"dialog-header": "Align to Freebase's Schemas",
"body-text": "The schema alignment skeleton below specifies how your grid-shaped data will be transformed into graph-shaped data in Freebase's schemas.",
"find-more": "Find out more ...",
"skeleton": "Skeleton",
"mql-preview": "MQL-like Preview",
"tripleloader-preview": "TripleLoader Preview"
},
"fb-dialogs": {
"sign-in": "Sign into Freebase",
"enable-loading": "to enable loading",
"error-new-topic": "Error creating new topic",
"error-loading-data": "Error loading data",
"add-info-source": "Click here to add a new information source",
"dialog-header": "Load Data into Freebase",
"no-triples-dataset": "This dataset has no triples",
"warning-aligned": "Have you aligned it with Freebase's schemas yet?",
"name-of-data": "Name of data load",
"source-id": "Source ID (optional)",
"bodytext-1": "Note: Your data will only be loaded into",
"bodytext-2": "Sandbox is where everyone can experiment with Freebase technologies without disruption to the official",
"bodytext-3": "Sandbox gets",
"sandbox-link": " Sandbox",
"freebase-link": " Freebase",
"refreshed-link": " refreshed periodically",
"bodytext-4": "In order to load your data into the official Freebase, you must first load it into Sandbox. Then it must pass a Quality Assurance (QA) process before it can be loaded into Freebase proper.",
"quality-assurance": "Quality assurance",
"bodytext-5": "After loaded into Sandbox, enlist other people's help to double-check this data load's quality so that it can be loaded into Freebase.",
"triple-schedule": "triples successfully scheduled for loading",
"follow-progress": "Follow the loading progress in the ",
"refinery-link": "Freebase Refinery",
"signed-as": "Signed in as:",
"sign-out": "Sign Out"
},
"fb-qa": {
"header": "QA Data Load?",
"bodytext-1": "Other people will be enlisted to help double-check your data load for quality assurance purposes. Their time and labor have a cost.",
"bodytext-2": "You yourself should have taken all reasonable measures to eliminate errors from your data load. Your prudence is greatly appreciated.",
"tell-more": "Tell me more ...",
"ok-button": "Yes, QA Data Load"
},
"fb-extend": {
"add-column": "Add Columns from Freebase Based on Column",
"warning-add-properties": "Please add some properties first.",
"querying-freebase": "Querying Freebase ...",
"remove-column": "Remove this column",
"add-constraints": "Add constraints to this column",
"mql-constraints": "Enter MQL query constraints as JSON",
"warning-valid-json": "Please ensure that the JSON you enter is valid.",
"warning-json-obj": "The JSON you enter must be an object, that is, it is of this form { ... }.",
"add-property": "Add Property",
"suggested-properties": "Suggested Properties",
"constraint": "Constraint"
},
"fb-buttons": {
"save": "Save",
"save-load": "Save & Load",
"close": "Close",
"reset": "Reset",
"cancel": "Cancel",
"align-now": "Align Now",
"settings": "Settings",
"preview": "Preview",
"load-sandbox": "Load to Sandbox",
"ok": "Ok"
}
}

View File

@ -0,0 +1,125 @@
{
"fb-schema-alignment": {
"close-confirm": "There are unsaved changes. Close anyway?",
"status-warning": "There are unsaved changes.",
"assert-link-found": "Assert link when 'true' is found in column",
"search-pick-property": "Search for a property or pick one below",
"search-property": "Search for a property",
"cell": "cell",
"cells": "cells",
"which-column": "Which column?",
"configure": "Configure...",
"which-topic": "Which topic?",
"what-value": "What value?",
"anonymous": "anonymous",
"add-property": "add property",
"anonymous-node": "Anonymous Node",
"freebase-topic": "Freebase Topic",
"value": "Value",
"skeleton-node": "Schema Alignment Skeleton Node",
"text": "text",
"int": "int",
"float": "float",
"double": "double",
"boolean": "boolean",
"date-time": "date/time",
"rawstring": "rawstring",
"set-to-cell": "Set to Cell in Column",
"cell-content-used": "The cell's content is used ...",
"specify-fb-topic": "to specify a Freebase topic, as reconciled",
"type-new-topics": "Type new topics as",
"literal-value": "as a literal value",
"literal-type": "Literal type",
"text-language": "Text language",
"key-namespace": "as a key in a namespace",
"namespace": "Namespace",
"generate-anonymous": "Generate an anonymous graph node",
"assign-type": "Assign a type to the node",
"use-existing-topic": "Use one existing Freebase topic",
"value-type": "Value type",
"language": "Language",
"use-literal-value": "Use a literal value",
"column-warning": "You must select at least one column",
"new-node-warning": "For creating a new graph node, you need to specify a type for it.",
"namespace-warning": "Please specify the namespace.",
"anonymous-node-warning": "For generating an anonymous graph node, you need to specify a type for it.",
"specify-topic-warning": "Please specify which existing Freebase topic to use",
"specify-value-warning": "Please specify the value to use"
},
"fb-interface": {
"dialog-header": "Align to Freebase's Schemas",
"body-text": "The schema alignment skeleton below specifies how your grid-shaped data will be transformed into graph-shaped data in Freebase's schemas.",
"find-more": "Find out more ...",
"skeleton": "Skeleton",
"mql-preview": "MQL-like Preview",
"tripleloader-preview": "TripleLoader Preview"
},
"fb-dialogs": {
"sign-in": "Sign into Freebase",
"enable-loading": "to enable loading",
"error-new-topic": "Error creating new topic",
"error-loading-data": "Error loading data",
"add-info-source": "Click here to add a new information source",
"dialog-header": "Load Data into Freebase",
"no-triples-dataset": "This dataset has no triples",
"warning-aligned": "Have you aligned it with Freebase's schemas yet?",
"name-of-data": "Name of data load",
"source-id": "Source ID (optional)",
"bodytext-1": "Note: Your data will only be loaded into",
"bodytext-2": "Sandbox is where everyone can experiment with Freebase technologies without disruption to the official",
"bodytext-3": "Sandbox gets",
"sandbox-link": " Sandbox",
"freebase-link": " Freebase",
"refreshed-link": " refreshed periodically",
"bodytext-4": "In order to load your data into the official Freebase, you must first load it into Sandbox. Then it must pass a Quality Assurance (QA) process before it can be loaded into Freebase proper.",
"quality-assurance": "Quality assurance",
"bodytext-5": "After loaded into Sandbox, enlist other people's help to double-check this data load's quality so that it can be loaded into Freebase.",
"triple-schedule": "triples successfully scheduled for loading",
"follow-progress": "Follow the loading progress in the ",
"refinery-link": "Freebase Refinery",
"signed-as": "Signed in as:",
"sign-out": "Sign Out"
},
"fb-qa": {
"header": "QA Data Load?",
"bodytext-1": "Other people will be enlisted to help double-check your data load for quality assurance purposes. Their time and labor have a cost.",
"bodytext-2": "You yourself should have taken all reasonable measures to eliminate errors from your data load. Your prudence is greatly appreciated.",
"tell-more": "Tell me more ...",
"ok-button": "Yes, QA Data Load"
},
"fb-extend": {
"add-column": "Add Columns from Freebase Based on Column",
"warning-add-properties": "Please add some properties first.",
"querying-freebase": "Querying Freebase ...",
"remove-column": "Remove this column",
"add-constraints": "Add constraints to this column",
"mql-constraints": "Enter MQL query constraints as JSON",
"warning-valid-json": "Please ensure that the JSON you enter is valid.",
"warning-json-obj": "The JSON you enter must be an object, that is, it is of this form { ... }.",
"add-property": "Add Property",
"suggested-properties": "Suggested Properties",
"constraint": "Constraint"
},
"fb-menu": {
"freebase": "Freebase",
"set-api-key": "Set Freebase API Key",
"align-schema": "Align to Freebase's schemas...",
"load": "Load into Freebase...",
"browse-data-load": "Browse data load details...",
"import-qa": "Import QA data",
"add-columns": "Add columns from Freebase ...",
"warning-load": "You have not tried to load the data in this project into Freebase yet."
},
"fb-buttons": {
"save": "Save",
"save-load": "Save & Load",
"close": "Close",
"reset": "Reset",
"cancel": "Cancel",
"align-now": "Align Now",
"settings": "Settings",
"preview": "Preview",
"load-sandbox": "Load to Sandbox",
"ok": "Ok"
}
}

View File

@ -0,0 +1,125 @@
{
"fb-schema-alignment": {
"close-confirm": "Ci sono cambiamenti non salvati. Chiudere comunque?",
"status-warning": "Ci sono cambiamenti non salvati.",
"assert-link-found": "Assert link when 'true' is found in column",
"search-pick-property": "Cerca una proprietà o scegline una dalle seguenti",
"search-property": "Cerca una proprietà",
"cell": "cella",
"cells": "celle",
"which-column": "Quale colonna?",
"configure": "Configura...",
"which-topic": "Quale topic?",
"what-value": "Quale valore?",
"anonymous": "anonimo",
"add-property": "aggiungi proprietà",
"anonymous-node": "Nodo Anonimo",
"freebase-topic": "Topic Freebase",
"value": "Valore",
"skeleton-node": "Schema Alignment Skeleton Node",
"text": "testo",
"int": "int",
"float": "float",
"double": "double",
"boolean": "boolean",
"date-time": "data/ora",
"rawstring": "rawstring",
"set-to-cell": "Set to Cell in Column",
"cell-content-used": "Il contenuto della cella è usato ...",
"specify-fb-topic": "per specificare un topic Freebase, come riconciliato",
"type-new-topics": "Inserisci il nuovo topic come",
"literal-value": "come un valore letterale",
"literal-type": "Tipo letterale",
"text-language": "Lingua di testo",
"key-namespace": "come una chiave nel namespace",
"namespace": "Namespace",
"generate-anonymous": "Genera un nodo anonimo nel grafo",
"assign-type": "Assegna un tipo al nodo",
"use-existing-topic": "Usa un topic Freebase esistente",
"value-type": "Tipo valore",
"language": "Lingua",
"use-literal-value": "Usa un valore letterale",
"column-warning": "Devi selezionare almeno una colonna",
"new-node-warning": "Per creare un nuovo nodo nel grafo, devi specificarne un tipo.",
"namespace-warning": "Specifica il namespace.",
"anonymous-node-warning": "Per generare un nodo anonimo nel grafo, devi specificarne un tipo.",
"specify-topic-warning": "Per favore specifica quale topic esistente di Freebase usare",
"specify-value-warning": "Per favore specifica il valore da usare"
},
"fb-interface": {
"dialog-header": "Allinea con gli schemi Freebase",
"body-text": "Lo scheletro per l'allineamento della schema specifica come i tuoi dati in formato tabellare saranno trasformati in un formato a grafo con lo schema di Freebase.",
"find-more": "Per saperne di più ...",
"skeleton": "Scheletro",
"mql-preview": "Anteprima MQL-like",
"tripleloader-preview": "Anteprima TripleLoader"
},
"fb-dialogs": {
"sign-in": "Accedi a Freebase",
"enable-loading": "per abilitare il caricamento",
"error-new-topic": "Errore nella creazione di un nuovo topic",
"error-loading-data": "Errore durante il caricamento dei dati",
"add-info-source": "Clicca qui per aggiungere una nuova sorgente di informazioni",
"dialog-header": "Carica i dati in Freebase",
"no-triples-dataset": "Questo dataset non ha triple",
"warning-aligned": "Hai già effettuato l'allineamento con lo schema Freebase?",
"name-of-data": "Nome del caricamento dati",
"source-id": "ID sorgente (opzionale)",
"bodytext-1": "Nota: i tuoi dati saranno caricati solamente in",
"bodytext-2": "Sandbox è dove chiunque può sperimentare le tecnologie Freebase senza creare danni all'ufficiale",
"bodytext-3": "Sandbox viene",
"sandbox-link": " Sandbox",
"freebase-link": " Freebase",
"refreshed-link": " aggiornata periodicamente",
"bodytext-4": "Per caricare i tuoi data su Freebase ufficiale, devi prima caricarli nel Sandbox. Successivamente, devono passare un processo di analisi qualitativa prima di essere caricati su Freebase.",
"quality-assurance": "Analisi qualitativa",
"bodytext-5": "Dopo essere caricati nella Sandbox, viene chiesto l'aiuto di altre persone per controllare due volte la qualità di questi dati in modo da poter poi essere caricati in Freebase.",
"triple-schedule": "triple pianificate con successo per il caricamento",
"follow-progress": "Segui il processo di caricamento nel ",
"refinery-link": "Freebase Refinery",
"signed-as": "Accesso effettuato come:",
"sign-out": "Esci"
},
"fb-qa": {
"header": "Caricamento dati con analisi qualitativa?",
"bodytext-1": "Alcune persone verranno incaricate per controllare i tuoi dati allo scopo di verificarne la qualità. Il loro tempo e lavoro ha un costo.",
"bodytext-2": "Tu stesso dovresti aver già effettuato la maggior parte dei controlli per assicurarti di aver rimosso errori dai dati. La tua prudenza è enormemente apprezzata.",
"tell-more": "Dimmi di più ...",
"ok-button": "Si, Caricamento dati con analisi qualitativa"
},
"fb-extend": {
"add-column": "Aggiungi colonne da Freebase basandoti sulla colonna",
"warning-add-properties": "Prima aggiungi delle proprietà.",
"querying-freebase": "Interrogando Freebase ...",
"remove-column": "Rimuovi questa colonna",
"add-constraints": "Aggiungi vincoli a questa colonna",
"mql-constraints": "Inserisci i vincoli per la query MQL come JSON",
"warning-valid-json": "Assicurati che l'oggetto JSON inserito sia valido.",
"warning-json-obj": "Il JSON che inserisci deve essere un oggetto, cioè in questa forma: { ... }.",
"add-property": "Aggiungi Proprietà",
"suggested-properties": "Proprietà suggerite",
"constraint": "Vincoli"
},
"fb-menu": {
"freebase": "Freebase",
"set-api-key": "Imposta l'API Key Freebase",
"align-schema": "Allinea con lo schema Freebase...",
"load": "Carica in Freebase...",
"browse-data-load": "Vedi i dettagli per il caricamento dati...",
"import-qa": "Importa dati con controllo qualità",
"add-columns": "Aggiungi colonne da Freebase ...",
"warning-load": "Non hai ancora provato a caricare i dati di questo progetto in Freebase."
},
"fb-buttons": {
"save": "Salva",
"save-load": "Salva & Carica",
"close": "Chiudi",
"reset": "Reset",
"cancel": "Cancella",
"align-now": "Allinea adesso",
"settings": "Settings",
"preview": "Anteprima",
"load-sandbox": "Carica nella Sandbox",
"ok": "Ok"
}
}

View File

@ -1,17 +1,12 @@
<div class="dialog-frame" style="width: 400px;">
<div class="dialog-header" bind="dialogHeader">QA Data Load?</div>
<div class="dialog-header" bind="dialogHeader"></div>
<div class="dialog-body" bind="dialogBody">
<p class="body-text">Other people will be enlisted to help double-check
your data load for quality assurance purposes. Their time and labor
have a cost.
</p>
<p class="body-text">You yourself should have taken all reasonable measures
to eliminate errors from your data load. Your prudence is greatly appreciated.
</p>
<p><a href="http://wiki.freebase.com/wiki/Refinery" target="_blank">Tell me more ...</a></p>
<p class="body-text" bind="bodytext1"></p>
<p class="body-text" bind="bodytext2"></p>
<p><a href="http://wiki.freebase.com/wiki/Refinery" target="_blank" bind="tellMore"></a></p>
</div>
<div class="dialog-footer" bind="dialogFooter">
<button class="button" bind="okButton">Yes, QA Data Load</button>
<button class="button" bind="cancelButton">Cancel</button>
<button class="button" bind="okButton"></button>
<button class="button" bind="cancelButton"></button>
</div>
</div>

View File

@ -3,16 +3,16 @@
<div class="dialog-body" bind="dialogBody">
<div class="grid-layout layout-normal layout-full"><table rows="4">
<tr>
<td width="300" height="1">Add Property</td>
<td width="300" height="1" ><span bind="fb_add_property"></span></td>
<td height="1">Preview</td>
<td height="1" width="1%"><button class="button" bind="resetButton">Reset</button></td>
<td height="1" width="1%"><button class="button" bind="resetButton"></button></td>
</tr>
<tr>
<td style="vertical-align: top;" height="1"><div class="input-container"><input bind="addPropertyInput" /></div></td>
<td style="vertical-align: top;" rowspan="3" colspan="2"><div class="preview-container" bind="previewContainer"></div></td>
</tr>
<tr>
<td height="1">Suggested Properties</td>
<td height="1" bind="suggested_properties"></td>
</tr>
<tr>
<td><div class="suggested-property-container" bind="suggestedPropertyContainer"></div></td>
@ -20,7 +20,7 @@
</table></div>
</div>
<div class="dialog-footer" bind="dialogFooter">
<button class="button" bind="okButton">&nbsp;&nbsp;OK&nbsp;&nbsp;</button>
<button class="button" bind="cancelButton">Cancel</button>
<button class="button" bind="okButton"></button>
<button class="button" bind="cancelButton"></button>
</div>
</div>

View File

@ -41,15 +41,23 @@ function ExtendDataPreviewDialog(column, columnIndex, rowIndices, onDone) {
var self = this;
this._dialog = $(DOM.loadHTML("freebase", "scripts/dialogs/extend-data-preview-dialog.html"));
this._elmts = DOM.bind(this._dialog);
this._elmts.dialogHeader.text("Add Columns from Freebase Based on Column " + column.name);
this._elmts.dialogHeader.text($.i18n._('fb-extend')["add-column"]);
this._elmts.fb_add_property.html($.i18n._('fb-extend')["add-property"]);
this._elmts.suggested_properties.text($.i18n._('fb-extend')["suggested-properties"]);
this._elmts.resetButton.text($.i18n._('fb-buttons')["reset"]);
this._elmts.okButton.html('&nbsp;&nbsp;'+$.i18n._('fb-buttons')["ok"]+'&nbsp;&nbsp;');
this._elmts.cancelButton.text($.i18n._('fb-buttons')["cancel"]);
this._elmts.resetButton.click(function() {
self._extension.properties = [];
self._update();
});
this._elmts.okButton.click(function() {
if (self._extension.properties.length === 0) {
alert("Please add some properties first.");
alert($.i18n._('fb-extend')["warning-add-properties"]);
} else {
DialogSystem.dismissUntil(self._level - 1);
self._onDone(self._extension);
@ -157,7 +165,7 @@ ExtendDataPreviewDialog.prototype._show = function(properties) {
};
ExtendDataPreviewDialog.prototype._update = function() {
this._elmts.previewContainer.empty().text("Querying Freebase ...");
this._elmts.previewContainer.empty().text($.i18n._('fb-extend')["querying-freebase"]);
var self = this;
var params = {
@ -234,7 +242,7 @@ ExtendDataPreviewDialog.prototype._renderPreview = function(data) {
$('<a href="javascript:{}"></a>')
.text("remove")
.addClass("action")
.attr("title", "Remove this column")
.attr("title", $.i18n._('fb-extend')["remove-column"])
.click(function() {
self._removeProperty(column.path);
}).appendTo(th);
@ -242,7 +250,7 @@ ExtendDataPreviewDialog.prototype._renderPreview = function(data) {
$('<a href="javascript:{}"></a>')
.text("constrain")
.addClass("action")
.attr("title", "Add constraints to this column")
.attr("title", $.i18n._('fb-extend')["add-constraints"])
.click(function() {
self._constrainProperty(column.path);
}).appendTo(th);
@ -329,14 +337,14 @@ ExtendDataPreviewDialog.prototype._constrainProperty = function(path) {
var frame = DialogSystem.createDialog();
frame.width("500px");
var header = $('<div></div>').addClass("dialog-header").text("Constrain " + path.join(" > ")).appendTo(frame);
var header = $('<div></div>').addClass("dialog-header").text(" " + path.join(" > ")).appendTo(frame);
var body = $('<div></div>').addClass("dialog-body").appendTo(frame);
var footer = $('<div></div>').addClass("dialog-footer").appendTo(frame);
body.html(
'<div class="grid-layout layout-normal layout-full"><table>' +
'<tr><td>' +
'Enter MQL query constraints as JSON' +
$.i18n._('fb-extend')["mql-constraints"] +
'</td></tr>' +
'<tr><td>' +
'<textarea style="width: 100%; height: 300px; font-family: monospace;" bind="textarea"></textarea>' +
@ -352,8 +360,8 @@ ExtendDataPreviewDialog.prototype._constrainProperty = function(path) {
}
footer.html(
'<button class="button" bind="okButton">&nbsp;&nbsp;OK&nbsp;&nbsp;</button>' +
'<button class="button" bind="cancelButton">Cancel</button>'
'<button class="button" bind="okButton">&nbsp;&nbsp;'+$.i18n._('fb-buttons')["ok"]+'&nbsp;&nbsp;</button>' +
'<button class="button" bind="cancelButton">'+$.i18n._('fb-buttons')["cancel"]+'</button>'
);
var footerElmts = DOM.bind(footer);
@ -367,7 +375,7 @@ ExtendDataPreviewDialog.prototype._constrainProperty = function(path) {
try {
var o = JSON.parse(bodyElmts.textarea[0].value);
if (o === undefined) {
alert("Please ensure that the JSON you enter is valid.");
alert($.i18n._('fb-extend')["warning-valid-json"]);
return;
}
@ -375,7 +383,7 @@ ExtendDataPreviewDialog.prototype._constrainProperty = function(path) {
o = o[0];
}
if (!$.isPlainObject(o)) {
alert("The JSON you enter must be an object, that is, it is of this form { ... }.");
alert($.i18n._('fb-extend')["warning-json-obj"]);
return;
}

View File

@ -1,44 +1,40 @@
<div class="dialog-frame" style="width: 800px;">
<div class="dialog-header" bind="dialogHeader">Load Data into Freebase</div>
<div class="dialog-header" bind="dialogHeader"></div>
<div class="dialog-body" bind="dialogBody">
<div bind="unalignedCase" style="display: none;" class="freebase-loading-tripleloader-message">
<h2>This dataset has no triples</h2>
<p>Have you aligned it with Freebase's schemas yet? <button class="button" bind="alignButton">Align Now</button></p>
<h2 bind="no_triples_dataset"></h2>
<p bind="warning_aligned"><button class="button" bind="alignButton"></button></p>
</div>
<div bind="functionalCase" style="display: none;">
<div class="refine-tabs" bind="functionalTabs">
<ul>
<li><a href="#freebase-loading-dialog-functional-tabs-settings">Settings</a></li>
<li><a href="#freebase-loading-dialog-functional-tabs-preview">Preview</a></li>
<li><a href="#freebase-loading-dialog-functional-tabs-settings" bind="settingsBtn"></a></li>
<li><a href="#freebase-loading-dialog-functional-tabs-preview" bind="previewBtn"></a></li>
</ul>
<div id="freebase-loading-dialog-functional-tabs-settings"
class="freebase-loading-dialog-functional-tab-panel"><div class="grid-layout layout-normal"><table>
<tr><td width="20%">Name of data load</td>
<tr><td width="20%" bind="name_of_data"></td>
<td colspan="2"><input type="text" size="40" id="freebase-loading-source-name" bind="source_name" /></td>
</tr>
<tr><td>Source ID (optional)</td>
<tr><td bind="source_id_label"></td>
<td colspan="2"><input type="text" size="60" id="freebase-loading-source-id" bind="source_id" /></td>
</tr>
<tr>
<td colspan="3">
<p class="body-text">Note: Your data will only be loaded into
<a href="http://www.sandbox-freebase.com/" target="_blank">Sandbox</a>.
Sandbox is where everyone can experiment with Freebase technologies without disruption
to the official <a href="http://www.freebase.com/">Freebase</a>. Sandbox gets
<a href="http://wiki.freebase.com/wiki/Sandbox" target="_blank">refreshed periodically</a>.
<p class="body-text"><span bind="bodytext1"></span>
<a href="http://www.sandbox-freebase.com/" target="_blank" bind="sandbox_link"></a>.
<span bind="bodytext2"> </span><a href="http://www.freebase.com/" bind="freebase_link"></a>.
<span bind="bodytext3"></span><a href="http://wiki.freebase.com/wiki/Sandbox"
target="_blank" bind="refreshed_link"></a>.
</p>
<p class="body-text">In order to load your data into the official Freebase, you must first load it
into Sandbox. Then it must pass a Quality Assurance (QA) process before it can
be loaded into Freebase proper.
<a href="http://wiki.freebase.com/wiki/Refinery" target="_blank">Find out more ...</a>
<p class="body-text" bind="bodytext4">
<a href="http://wiki.freebase.com/wiki/Refinery" target="_blank" bind="findOutMore"></a>
</p>
</td>
</tr>
<tr><td>Quality assurance</td>
<tr><td bind="quality_assurance"></td>
<td><input bind="qaCheckbox" type="checkbox" name="qa" value="qa" /></td>
<td>After loaded into Sandbox, enlist other people's help to double-check
this data load's quality so that it can be loaded into Freebase.
</td>
<td bind="bodytext5"></td>
</tr>
</table></div></div>
<div id="freebase-loading-dialog-functional-tabs-preview"
@ -49,8 +45,8 @@
</div>
</div>
<div bind="loadedCase" style="display: none;" class="freebase-loading-tripleloader-message">
<h2><span bind="tripleCountSpan"></span> triples successfully scheduled for loading</h2>
<h4>Follow the loading progress in the <a bind="refineryLink" target="_new">Freebase Refinery</a>.</h4>
<h2><span bind="tripleCountSpan"></span> <span bind="triple_success_load"></span></h2>
<h4><span bind="follow_progress"></span> <a bind="refineryLink" target="_new"></a>.</h4>
</div>
<div bind="errorCase" style="display: none;" class="freebase-loading-tripleloader-message">
<h2 bind="errorMessage"></h2>
@ -59,13 +55,13 @@
</div>
<div class="dialog-footer" bind="dialogFooter"><div class="grid-layout layout-normal layout-full"><table><tr>
<td bind="left" style="text-align: left" width="60%" nowrap="true">
<button class="button" bind="cancelButton" id="freebase-loading-cancel">Cancel</button>
<button class="button" bind="cancelButton" id="freebase-loading-cancel"></button>
</td>
<td bind="center" style="text-align: right" width="20%" nowrap="true">
<div bind="authorization" class="freebase-loading-authorization"></div>
</td>
<td bind="right" style="text-align: right" width="20%" nowrap="true">
<button class="button button-primary button-disabled" bind="loadButton" id="freebase-loading-load" disabled>Load to Sandbox</button>
<button class="button button-primary button-disabled" bind="loadButton" id="freebase-loading-load" disabled></button>
</td>
</tr></table></div></div>
</div>

View File

@ -45,13 +45,37 @@ FreebaseLoadingDialog.prototype._createDialog = function() {
var provider = "freebase.com";
var authorization = this._elmts.authorization;
var loadButton = this._elmts.loadButton;
this._elmts.dialogHeader.text($.i18n._('fb-dialogs')["dialog-header"]);
this._elmts.no_triples_dataset.text($.i18n._('fb-dialogs')["no-triples-dataset"]);
this._elmts.warning_aligned.text($.i18n._('fb-dialogs')["warning-aligned"]);
this._elmts.alignButton.text($.i18n._('fb-buttons')["align-now"]);
this._elmts.settingsBtn.text($.i18n._('fb-buttons')["settings"]);
this._elmts.previewBtn.text($.i18n._('fb-buttons')["preview"]);
this._elmts.name_of_data.text($.i18n._('fb-dialogs')["name-of-data"]);
this._elmts.source_id_label.text($.i18n._('fb-dialogs')["source-id"]);
this._elmts.bodytext1.text($.i18n._('fb-dialogs')["bodytext-1"]);
this._elmts.bodytext2.text($.i18n._('fb-dialogs')["bodytext-2"]);
this._elmts.bodytext3.text($.i18n._('fb-dialogs')["bodytext-3"]);
this._elmts.sandbox_link.text($.i18n._('fb-dialogs')["sandbox-link"]);
this._elmts.freebase_link.text($.i18n._('fb-dialogs')["freebase-link"]);
this._elmts.refreshed_link.text($.i18n._('fb-dialogs')["refreshed-link"]);
this._elmts.bodytext4.text($.i18n._('fb-dialogs')["bodytext-4"]);
this._elmts.findOutMore.text($.i18n._('fb-interface')["find-more"]);
this._elmts.quality_assurance.text($.i18n._('fb-dialogs')["quality-assurance"]);
this._elmts.bodytext5.text($.i18n._('fb-dialogs')["bodytext-5"]);
this._elmts.triple_success_load.text($.i18n._('fb-dialogs')["triple-schedule"]);
this._elmts.follow_progress.text($.i18n._('fb-dialogs')["follow-progress"]);
this._elmts.refineryLink.text($.i18n._('fb-dialogs')["refinery-link"]);
this._elmts.cancelButton.text($.i18n._('fb-buttons')["cancel"]);
this._elmts.loadButton.text($.i18n._('fb-buttons')["load-sandbox"]);
// TODO: Does this need to be redone for the new API / freebase.com site?
var check_authorization = function(cont) {
var check_authorization_url = "command/freebase/check-authorization/" + provider;
$.get(check_authorization_url, function(data) {
if ("status" in data && data.code == "/api/status/ok") {
authorization.html('Signed in as: <a target="_new" href="http://www.freebase.com/view/user/' + data.username + '">' + data.username + '</a> | <a href="javascript:{}" bind="signout">Sign Out</a>').show();
authorization.html($.i18n._('fb-dialogs')["signed-as"]+' <a target="_new" href="http://www.freebase.com/view/user/' + data.username + '">' + data.username + '</a> | <a href="javascript:{}" bind="signout">'+$.i18n._('fb-dialogs')["sign-out"]+'</a>').show();
DOM.bind(authorization).signout.click(function() {
self._signedin = false;
loadButton.attr("disabled","disabled");
@ -71,7 +95,7 @@ FreebaseLoadingDialog.prototype._createDialog = function() {
if (typeof cont == "function") cont(data);
} else {
authorization.html('<a href="javascript:{}" bind="signin">Sign into Freebase</a> to enable loading').show();
authorization.html('<a href="javascript:{}" bind="signin">'+$.i18n._('fb-dialogs')["sign-in"]+'</a> '+$.i18n._('fb-dialogs')["enable-loading"]).show();
self._signedin = false;
$("#freebase-loading-source-name").keyup();
@ -104,7 +128,7 @@ FreebaseLoadingDialog.prototype._createDialog = function() {
self._elmts.source_id.val(data.result[0].id);
if (typeof cont == "function") cont();
} else {
self._show_error("Error creating new topic", data);
self._show_error($.i18n._('fb-dialogs')["error-new-topic"], data);
}
},
"json"
@ -137,7 +161,7 @@ FreebaseLoadingDialog.prototype._createDialog = function() {
self._elmts.source_id.suggest({
filter: "(all type:/dataworld/information_source)",
suggest_new: "Click here to add a new information source"
suggest_new: $.i18n._('fb-dialogs')["add-info-source"]
}).bind("fb-select", function(e, data) {
self._elmts.source_id.val(data.id);
}).bind("fb-select-new", function(e, val) {
@ -202,7 +226,7 @@ FreebaseLoadingDialog.prototype._load = function() {
self._elmts.loadedCase.show();
self._end();
} else {
self._show_error("Error loading data",data);
self._show_error($.i18n._('fb-dialogs')["error-loading-data"],data);
}
},
"json"
@ -216,6 +240,13 @@ FreebaseLoadingDialog.prototype._load = function() {
var dismiss = function() {
DialogSystem.dismissUntil(level - 1);
};
this._elmts.refineryLink.text($.i18n._('fb-qa')["header"]);
this._elmts.bodytext1.text($.i18n._('fb-qa')["bodytext-1"]);
this._elmts.bodytext2.text($.i18n._('fb-qa')["bodytext-2"]);
this._elmts.tellMore.text($.i18n._('fb-qa')["tell-more"]);
this._elmts.okButton.text($.i18n._('fb-qa')["ok-button"]);
this._elmts.cancelButton.text($.i18n._('fb-qa')["ok-button"]);
elmts.okButton.click(function() {
doLoad();

View File

@ -101,7 +101,7 @@ SchemaAlignment._batchSearch = function(queries, onDone) {
// TODO: New API doesn't accept multiple queries
// args.push("https://www.googleapis.com/freebase/v1/search?key=" + Freebase.API_KEY + "&" +
args.push("http://api.freebase.com/api/service/search?" +
args.push("http://api.freebase.com/api/service/search?" + // FIXME:
$.param({ "queries" : JSON.stringify(batch) }) + "&callback=?");
args.push(null); // no data
@ -234,6 +234,17 @@ SchemaAlignmentDialog.prototype._createDialog = function() {
DialogSystem.dismissUntil(self._level - 1);
};
elmts.dialogHeader.text($.i18n._('fb-interface')["dialog-header"]);
elmts.body_text.text($.i18n._('fb-interface')["body-text"]);
elmts.find_more.text($.i18n._('fb-interface')["find-more"]);
elmts.skeleton.text($.i18n._('fb-interface')["skeleton"]);
elmts.skeleton.text($.i18n._('fb-interface')["mql-preview"]);
elmts.skeleton.text($.i18n._('fb-interface')["tripleloader-preview"]);
elmts.saveButton.text($.i18n._('fb-buttons')["save"]);
elmts.saveAndLoadButton.text($.i18n._('fb-buttons')["save-load"]);
elmts.closeButton.text($.i18n._('fb-buttons')["close"]);
elmts.resetButton.text($.i18n._('fb-buttons')["reset"]);
elmts.saveButton.click(function() {
self._save();
});
@ -247,7 +258,7 @@ SchemaAlignmentDialog.prototype._createDialog = function() {
self._reset(null);
});
elmts.closeButton.click(function() {
if (!self._hasUnsavedChanges || window.confirm("There are unsaved changes. Close anyway?")) {
if (!self._hasUnsavedChanges || window.confirm($.i18n._('fb-schema-alignment')["close-confirm"])) {
dismiss();
}
});
@ -281,7 +292,7 @@ SchemaAlignmentDialog.prototype.preview = function(initial) {
this._previewPanes.empty();
if (!(initial)) {
this._elmts.statusIndicator.show().text("There are unsaved changes.");
this._elmts.statusIndicator.show().text($.i18n._('fb-schema-alignment')["status-warning"]);
this._hasUnsavedChanges = true;
}

View File

@ -1,16 +1,14 @@
<div class="dialog-frame" style="width: 800px;">
<div class="dialog-header" bind="dialogHeader">Align to Freebase's Schemas</div>
<div class="dialog-header" bind="dialogHeader"></div>
<div class="dialog-body" bind="dialogBody">
<p class="body-text">
The schema alignment skeleton below specifies how your grid-shaped data will be
transformed into graph-shaped data in Freebase's schemas.
<a href="http://code.google.com/p/google-refine/wiki/SchemaAlignment" target="_blank">Find out more ...</a>
<p class="body-text" bind="body_text">
<a href="https://github.com/OpenRefine/OpenRefine/wiki/Schema-Alignment" target="_blank" bind="find_more"></a>
</p>
<div id="schema-alignment-tabs" class="refine-tabs">
<ul>
<li><a href="#schema-alignment-tabs-protograph">Skeleton</a></li>
<li><a href="#schema-alignment-tabs-preview-mqllike">MQL-like Preview</a></li>
<li><a href="#schema-alignment-tabs-preview-tripleloader">TripleLoader Preview</a></li>
<li><a href="#schema-alignment-tabs-protograph" bind="skeleton"></a></li>
<li><a href="#schema-alignment-tabs-preview-mqllike" bind="mql_preview"></a></li>
<li><a href="#schema-alignment-tabs-preview-tripleloader" bind="tripleloader_preview"></a></li>
</ul>
<div id="schema-alignment-tabs-protograph">
<div class="schema-alignment-dialog-canvas"></div>
@ -25,17 +23,17 @@
</div>
<div class="dialog-footer" bind="dialogFooter"><div class="grid-layout layout-normal layout-full"><table><tr>
<td>
<button class="button" bind="resetButton">Reset</button>
<button class="button" bind="resetButton"></button>
</td>
<td style="text-align:right;">
<button class="button button-primary" bind="saveButton">Save</button>
<button class="button" bind="saveAndLoadButton">Save &amp; Load</button>
<button class="button button-primary" bind="saveButton"></button>
<button class="button" bind="saveAndLoadButton"></button>
</td>
<td style="text-align:center;" width="30%">
<span class="schema-alignment-status-indicator" bind="statusIndicator"></span>
</td>
<td style="text-align:right;" width="1%">
<button class="button" bind="closeButton">Close</button>
<button class="button" bind="closeButton"></button>
</td>
</tr></table></div></div>
</div>

View File

@ -239,7 +239,7 @@ SchemaAlignmentDialog.UILink.prototype._showPropertySuggestPopup = function(elmt
var divConditional = $('<div>')
.addClass("schema-alignment-link-menu-section")
.html("Assert link when 'true' is found in column<br/>").appendTo(menu);
.html($.i18n._('fb-schema-alignment')["assert-link-found"]+"<br/>").appendTo(menu);
var conditionalSelect = $('<select>').appendTo(divConditional);
$('<option>')
@ -266,7 +266,7 @@ SchemaAlignmentDialog.UILink.prototype._showPropertySuggestPopup = function(elmt
divSearch = $('<div>')
.addClass("schema-alignment-link-menu-section")
.css("margin-bottom", "2em")
.html('<div>Search for a property or pick one below</div>').appendTo(menu);
.html('<div>'+$.i18n._('fb-schema-alignment')["search-pick-property"]+'</div>').appendTo(menu);
var createSuggestion = function(suggestion) {
var menuItem = MenuSystem.createMenuItem().appendTo(menu);
@ -296,7 +296,7 @@ SchemaAlignmentDialog.UILink.prototype._showPropertySuggestPopup = function(elmt
} else {
divSearch = $('<div>')
.addClass("schema-alignment-link-menu-section-last")
.html('<div>Search for a property</div>').appendTo(menu);
.html('<div>'+$.i18n._('fb-schema-alignment')["search-property"]+'</div>').appendTo(menu);
}
var input = $('<input />').appendTo($('<div>').appendTo(divSearch));

View File

@ -124,9 +124,12 @@ SchemaAlignmentDialog.UINode.prototype._renderMain = function() {
.appendTo(a);
}
$('<span>').text(this._node.columnNames.length > 1 ? " cells" : " cell").appendTo(a);
$('<span>').text(
this._node.columnNames.length > 1 ? " "
+ $.i18n._('fb-schema-alignment')["cells"] : " "
+ $.i18n._('fb-schema-alignment')["cell"]).appendTo(a);
} else {
a.html(this._options.mustBeCellTopic ? "Which column?" : "Configure...");
a.html(this._options.mustBeCellTopic ? $.i18n._('fb-schema-alignment')["which-column"] : $.i18n._('fb-schema-alignment')["configure"]);
}
} else if (this._node.nodeType == "topic") {
if ("topic" in this._node) {
@ -134,16 +137,16 @@ SchemaAlignmentDialog.UINode.prototype._renderMain = function() {
} else if ("id" in this._node) {
a.html(this._node.topic.id);
} else {
a.html("Which topic?");
a.html($.i18n._('fb-schema-alignment')["which-topic"]);
}
} else if (this._node.nodeType == "value") {
if ("value" in this._node) {
a.html(this._node.value);
} else {
a.html("What value?");
a.html($.i18n._('fb-schema-alignment')["what-value"]);
}
} else if (this._node.nodeType == "anonymous") {
a.html("(anonymous)");
a.html("("+$.i18n._('fb-schema-alignment')["anonymous"]+")");
}
};
@ -212,7 +215,7 @@ SchemaAlignmentDialog.UINode.prototype._renderDetails = function() {
$('<a href="javascript:{}"></a>')
.addClass("action")
.text("add property")
.text($.i18n._('fb-schema-alignment')["add-property"])
.appendTo(divFooter)
.click(function() {
var newLink = {
@ -241,7 +244,7 @@ SchemaAlignmentDialog.UINode.prototype._showColumnPopupMenu = function(elmt) {
if (!this._options.mustBeCellTopic) {
menu.push({
label: "Anonymous Node",
label: $.i18n._('fb-schema-alignment')["anonymous-node"],
click: function() {
self._node.nodeType = "anonymous";
self._showExpandable();
@ -249,7 +252,7 @@ SchemaAlignmentDialog.UINode.prototype._showColumnPopupMenu = function(elmt) {
}
});
menu.push({
label: "Freebase Topic",
label: $.i18n._('fb-schema-alignment')["freebase-topic"],
click: function() {
self._node.nodeType = "topic";
self._hideExpandable();
@ -257,7 +260,7 @@ SchemaAlignmentDialog.UINode.prototype._showColumnPopupMenu = function(elmt) {
}
});
menu.push({
label: "Value",
label: $.i18n._('fb-schema-alignment')["value"],
click: function() {
self._node.nodeType = "value";
self._hideExpandable();
@ -292,7 +295,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
frame.width("750px");
var header = $('<div></div>').addClass("dialog-header").text("Schema Alignment Skeleton Node").appendTo(frame);
var header = $('<div></div>').addClass("dialog-header").text($.i18n._('fb-schema-alignment')["skeleton-node"]).appendTo(frame);
var body = $('<div></div>').addClass("dialog-body").appendTo(frame);
var footer = $('<div></div>').addClass("dialog-footer").appendTo(frame);
@ -301,13 +304,13 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
*--------------------------------------------------
*/
var literalTypeSelectHtml =
'<option value="/type/text" checked>text</option>' +
'<option value="/type/int">int</option>' +
'<option value="/type/float">float</option>' +
'<option value="/type/double">double</option>' +
'<option value="/type/boolean">boolean</option>' +
'<option value="/type/datetime">date/time</option>' +
'<option value="/type/rawstring">rawstring</option>';
'<option value="/type/text" checked>'+$.i18n._('fb-schema-alignment')["text"]+'</option>' +
'<option value="/type/int">'+$.i18n._('fb-schema-alignment')["int"]+'</option>' +
'<option value="/type/float">'+$.i18n._('fb-schema-alignment')["float"]+'</option>' +
'<option value="/type/double">'+$.i18n._('fb-schema-alignment')["double"]+'</option>' +
'<option value="/type/boolean">'+$.i18n._('fb-schema-alignment')["boolean"]+'</option>' +
'<option value="/type/datetime">'+$.i18n._('fb-schema-alignment')["date-time"]+'</option>' +
'<option value="/type/rawstring">'+$.i18n._('fb-schema-alignment')["rawstring"]+'</option>';
var html = $(
'<div class="grid-layout layout-looser layout-full"><table>' +
@ -317,7 +320,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'<tr>' +
'<td>' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="cell-as" bind="radioNodeTypeCellAs" /> Set to Cell in Column' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="cell-as" bind="radioNodeTypeCellAs" /> '+$.i18n._('fb-schema-alignment')["set-to-cell"]+'' +
'</div>' +
'</td>' +
'</tr>' +
@ -329,15 +332,15 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'<td>' +
'<div class="grid-layout layout-tight"><table cols="4">' +
'<tr>' +
'<td colspan="4">The cell\'s content is used ...</td>' +
'<td colspan="4">'+$.i18n._('fb-schema-alignment')["cell-content-used"]+'</td>' +
'</tr>' +
'<tr>' +
'<td><input type="radio" name="schema-align-node-dialog-node-subtype" value="cell-as-topic" bind="radioNodeTypeCellAsTopic" /></td>' +
'<td colspan="3">to specify a Freebase topic, as reconciled</td>' +
'<td colspan="3">'+$.i18n._('fb-schema-alignment')["specify-fb-topic"]+'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td colspan="3">Type new topics as</td>' +
'<td colspan="3">'+$.i18n._('fb-schema-alignment')["type-new-topic"]+'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
@ -345,26 +348,26 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'</tr>' +
'<tr>' +
'<td><input type="radio" name="schema-align-node-dialog-node-subtype" value="cell-as-value" bind="radioNodeTypeCellAsValue" /></td>' +
'<td colspan="3">as a literal value</td>' +
'<td colspan="3">'+$.i18n._('fb-schema-alignment')["literal-value"]+'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td colspan="2">Literal type</td>' +
'<td colspan="2">'+$.i18n._('fb-schema-alignment')["literal-type"]+'</td>' +
'<td colspan="1"><select bind="cellAsValueTypeSelect">' + literalTypeSelectHtml + '</select></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td colspan="2">Text language</td>' +
'<td colspan="2">'+$.i18n._('fb-schema-alignment')["text-language"]+'</td>' +
'<td colspan="1"><input bind="cellAsValueLanguageInput" /></td>' +
'</tr>' +
'<tr>' +
'<td><input type="radio" name="schema-align-node-dialog-node-subtype" value="cell-as-key" bind="radioNodeTypeCellAsKey" /></td>' +
'<td colspan="3">as a key in a namespace</td>' +
'<td colspan="3">'+$.i18n._('fb-schema-alignment')["key-namespace"]+'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td colspan="2">Namespace</td>' +
'<td colspan="2">'+$.i18n._('fb-schema-alignment')["namespace"]+'</td>' +
'<td colspan="1"><input bind="cellAsKeyInput" /></td>' +
'</tr>' +
'</table></div>' +
@ -381,20 +384,20 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="anonymous" bind="radioNodeTypeAnonymous" /> Generate an anonymous graph node' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="anonymous" bind="radioNodeTypeAnonymous" /> '+$.i18n._('fb-schema-alignment')["generate-anonymous"]+'' +
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Assign a type to the node</td>' +
'<td>'+$.i18n._('fb-schema-alignment')["assign-type"]+'</td>' +
'<td>&nbsp;<input bind="anonymousNodeTypeInput" /></td>' +
'</tr>' +
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="topic" bind="radioNodeTypeTopic" /> Use one existing Freebase topic' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="topic" bind="radioNodeTypeTopic" /> '+$.i18n._('fb-schema-alignment')["use-existing-topic"]+'' +
'</div>' +
'</td>' +
'</tr>' +
@ -407,23 +410,23 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
'<tr>' +
'<td colspan="3">' +
'<div class="schema-align-node-dialog-node-type">' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="value" bind="radioNodeTypeValue" /> Use a literal value' +
'<input type="radio" name="schema-align-node-dialog-node-type" value="value" bind="radioNodeTypeValue" /> '+$.i18n._('fb-schema-alignment')["use-literal-value"]+
'</div>' +
'</td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value</td>' +
'<td>'+$.i18n._('fb-schema-alignment')["value"]+'</td>' +
'<td><input bind="valueNodeTypeValueInput" /></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Value type</td>' +
'<td>'+$.i18n._('fb-schema-alignment')["value-type"]+'</td>' +
'<td><select bind="valueNodeTypeValueTypeSelect">' + literalTypeSelectHtml + '</select></td>' +
'</tr>' +
'<tr>' +
'<td></td>' +
'<td>Language</td>' +
'<td>'+$.i18n._('fb-schema-alignment')["language"]+'</td>' +
'<td><input bind="valueNodeTypeLanguageInput" /></td>' +
'</tr>' +
'</table></div>' +
@ -581,14 +584,14 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
}).get();
if (node.columnNames.length == 0) {
alert("You must select at least one column.");
alert($.i18n._('fb-schema-alignment')["column-warning"]);
return null;
}
if (node.nodeType == "cell-as-topic") {
var t = elmts.cellAsTopicNodeTypeInput.data("data.suggest");
if (!(t)) {
alert("For creating a new graph node, you need to specify a type for it.");
alert($.i18n._('fb-schema-alignment')["new-node-warning"]);
elmts.cellAsTopicNodeTypeInput.focus();
return null;
}
@ -606,7 +609,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
} else if (node.nodeType == "cell-as-key") {
var t = elmts.cellAsKeyInput.data("data.suggest");
if (!(t)) {
alert("Please specify the namespace.");
alert($.i18n._('fb-schema-alignment')["namespace-warning"]);
return null;
}
node.namespace = {
@ -617,7 +620,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
} else if (node.nodeType == "anonymous") {
var t = elmts.anonymousNodeTypeInput.data("data.suggest");
if (!(t)) {
alert("For generating an anonymous graph node, you need to specify a type for it.");
alert($.i18n._('fb-schema-alignment')["anonymous-node-warning"]);
return null;
}
node.type = {
@ -627,7 +630,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
} else if (node.nodeType == "topic") {
var t = elmts.topicNodeTypeInput.data("data.suggest");
if (!(t)) {
alert("Please specify which existing Freebase topic to use.");
alert($.i18n._('fb-schema-alignment')["specify-topic-warning"]);
return null;
}
node.topic = {
@ -637,7 +640,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
} else if (node.nodeType == "value") {
node.value = $.trim(elmts.valueNodeTypeValueInput[0].value);
if (!node.value.length) {
alert("Please specify the value to use.");
alert($.i18n._('fb-schema-alignment')["specify-value-warning"]);
return null;
}
node.valueType = elmts.valueNodeTypeValueTypeSelect[0].value;
@ -662,7 +665,7 @@ SchemaAlignmentDialog.UINode.prototype._showNodeConfigDialog = function() {
}
}).appendTo(footer);
$('<button class="button"></button>').text("Cancel").click(function() {
$('<button class="button"></button>').text($.i18n._('fb-buttons')["cancel"]).click(function() {
DialogSystem.dismissUntil(level - 1);
}).appendTo(footer);

View File

@ -33,6 +33,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var FreebaseExtension = { handlers: {} };
// Internationalization init
var lang = navigator.language.split("-")[0]
|| navigator.userLanguage.split("-")[0];
var dictionary = "";
$.ajax({
url : "/command/freebase/load-language?",
type : "POST",
async : false,
data : {
lng : lang
},
success : function(data) {
dictionary = data;
}
});
$.i18n.setDictionary(dictionary);
// End internationalization
FreebaseExtension.handlers.setFreebaseApiKey = function() {
var value = window.prompt("Set Freebase API Key:");
if (value !== null) {
@ -79,7 +98,7 @@ FreebaseExtension.handlers.browseToDataLoad = function() {
null,
function(data) {
if (data.value == null) {
alert("You have not tried to load the data in this project into Freebase yet.");
alert($.i18n._('fb-menu')["warning-load"]);
} else {
$(form).attr("action", "http://refinery.freebaseapps.com/load/" + data.value);
form.submit();
@ -101,33 +120,35 @@ FreebaseExtension.handlers.importQAData = function() {
};
ExtensionBar.addExtensionMenu({
"id" : "freebase",
"label" : "Freebase",
"label" : $.i18n._('fb-menu')["freebase"],
"submenu" : [
{
"id" : "freebase/set-api-key",
label: "Set Freebase API Key",
label: $.i18n._('fb-menu')["set-api-key"],
click: FreebaseExtension.handlers.setFreebaseApiKey
},
{
"id" : "freebase/schema-alignment",
label: "Align to Freebase's schemas...",
label: $.i18n._('fb-menu')["align-schema"],
click: function() { FreebaseExtension.handlers.editSchemaAlignment(false); }
},
{
"id" : "freebase/load-info-freebase",
label: "Load into Freebase...",
label: $.i18n._('fb-menu')["load"],
click: function() { FreebaseExtension.handlers.loadIntoFreebase(); }
},
{},
{
"id" : "freebase/browse-load",
label: "Browse data load details...",
label: $.i18n._('fb-menu')["browse-data-load"],
click: function() { FreebaseExtension.handlers.browseToDataLoad(); }
},
{
"id" : "freebase/import-qa-data",
label: "Import QA data",
label: $.i18n._('fb-menu')["import-qa"],
click: function() { FreebaseExtension.handlers.importQAData(); }
}
]
@ -163,7 +184,7 @@ DataTableColumnHeaderUI.extendMenu(function(column, columnHeaderUI, menu) {
[ "core/edit-column", "core/add-column-by-fetching-urls" ],
{
id: "freebase/add-columns-from-freebase",
label: "Add columns from Freebase ...",
label: $.i18n._('fb-menu')["add-columns"],
click: doAddColumnFromFreebase
}
);

View File

@ -0,0 +1,73 @@
package com.google.refine.freebase.commands;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.refine.ProjectManager;
import com.google.refine.commands.Command;
public class LoadLanguageCommand extends Command {
public LoadLanguageCommand() {
// TODO Auto-generated constructor stub
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String rawDirectoryFile = request.getSession().getServletContext()
.getRealPath("extensions/freebase/module/langs/");
String cleanedDirectory = rawDirectoryFile.replace("main" + File.separator + "webapp" + File.separator, "");
BufferedReader reader = null;String param = null;
try {
param = (String) ProjectManager.singleton.getPreferenceStore().get("userLang");
} catch (NullPointerException e) {
}
if (param == null) param = request.getParameter("lng");
String[] langs = param.split(" ");
try {
String file = cleanedDirectory + File.separator + "translation-" + langs[0] + ".json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e1) {
try {
String file = cleanedDirectory + File.separator + "translation-default.json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e3) {
e3.printStackTrace();
}
}
String line = null;
String message = new String();
if (reader != null) {
while ((line = reader.readLine()) != null) {
// buffer.append(line);
message += line + System.getProperty("line.separator");
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(message);
response.getWriter().flush();
response.getWriter().close();
}
}

View File

@ -2,8 +2,8 @@
<!--+
|
| OpenRefine GData Extension Build File
|
| OpenRefine GData Extension Build File
|
+-->
<project name="grefine-gdata-extension" default="build" basedir=".">
@ -50,7 +50,7 @@
<target name="build_java">
<mkdir dir="${classes.dir}" />
<javac encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<javac source="${java_version}" target="${java_version}" encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<src path="${src.dir}"/>
<classpath refid="class.path" />
</javac>

View File

@ -51,6 +51,7 @@ function init() {
RS.registerCommand(module, "deauthorize", Packages.com.google.refine.extension.gdata.DeAuthorizeCommand());
RS.registerCommand(module, "upload", Packages.com.google.refine.extension.gdata.UploadCommand());
// TODO: Need a new OAUTH2 authorize command for FusionTables
RS.registerCommand(module, "load-language", Packages.com.google.refine.extension.gdata.commands.LoadLanguageCommand());
// Register importer and exporter
var IM = Packages.com.google.refine.importing.ImportingManager;

View File

@ -34,7 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<html lang="en">
<head>
<meta charset="utf-8">
<title>OpenRefine - Authorization</title>
<title id="gdata-authorize"></title>
</head>
<body>
<script>

View File

@ -37,7 +37,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
<title>OpenRefine - Authorized</title>
</head>
<body>
Authorization process completed. Close this window and return to OpenRefine.
<span id="gdata-authorized"></span>
<script>
var windowName = "$winname";

View File

@ -0,0 +1,56 @@
{
"gdata-import": {
"preparing": "Preparing ...",
"creating": "Creating project ...",
"title": "Public Documents",
"import-by-url": "Import a <em>public</em> Google Spreadsheet or Fusion Table by its URL:",
"next->": "Next &raquo;",
"auth-doc": "Authorized Documents",
"please": "Please",
"sign-in": "sign in and authorize",
"sign-out": "sign out",
"access-data": "access to your Google data.",
"retrieving": "Retrieving Google Docs documents ...",
"re-sign-in": "re-sign in",
"another-account": "with another account"
},
"gdata-parsing": {
"start-over": "&laquo; Start Over",
"conf-pars": "Configure Parsing Options",
"proj-name": "Project&nbsp;name",
"create-proj": "Create Project &raquo;",
"updating-preview": "Updating preview ...",
"worksheet": "Worksheets",
"option": "Options",
"preview-button": "Update&nbsp;Preview",
"ignore-first": "Ignore first",
"ignore": "line(s) at beginning of file",
"parse-next": "Parse next",
"parse": "line(s) as column headers",
"discard-next": "Discard initial",
"discard": "row(s) of data",
"limit-next": "Load at most",
"limit": "row(s) of data",
"store-row": "Store blank rows",
"store-cell": "Store blank cells as nulls"
},
"gdata-source": {
"alert-url": "You must specify a web address (URL) to import.",
"type": "Type",
"title": "Title",
"authors": "Authors",
"updated": "Updated"
},
"gdata-exporter": {
"uploading": "Uploading...",
"upload-error": "Upload error: ",
"new-spreadsheet": "A new Google spreadsheet",
"enter-spreadsheet": "Enter a name for the new Google spreadsheet",
"new-fusion": "A new Google Fusion table",
"enter-fusion": "Enter a name for the new Google Fusion table"
},
"gdata-auth": {
"authorize-label": "OpenRefine - Authorization",
"authorized-label": "Authorization process completed. Close this window and return to OpenRefine."
}
}

View File

@ -0,0 +1,56 @@
{
"gdata-import": {
"preparing": "Preparing ...",
"creating": "Creating project ...",
"title": "Public Documents",
"import-by-url": "Import a <em>public</em> Google Spreadsheet or Fusion Table by its URL:",
"next->": "Next &raquo;",
"auth-doc": "Authorized Documents",
"please": "Please",
"sign-in": "sign in and authorize",
"sign-out": "sign out",
"access-data": "access to your Google data.",
"retrieving": "Retrieving Google Docs documents ...",
"re-sign-in": "re-sign in",
"another-account": "with another account"
},
"gdata-parsing": {
"start-over": "&laquo; Start Over",
"conf-pars": "Configure Parsing Options",
"proj-name": "Project&nbsp;name",
"create-proj": "Create Project &raquo;",
"updating-preview": "Updating preview ...",
"worksheet": "Worksheets",
"option": "Options",
"preview-button": "Update&nbsp;Preview",
"ignore-first": "Ignore first",
"ignore": "line(s) at beginning of file",
"parse-next": "Parse next",
"parse": "line(s) as column headers",
"discard-next": "Discard initial",
"discard": "row(s) of data",
"limit-next": "Load at most",
"limit": "row(s) of data",
"store-row": "Store blank rows",
"store-cell": "Store blank cells as nulls"
},
"gdata-source": {
"alert-url": "You must specify a web address (URL) to import.",
"type": "Type",
"title": "Title",
"authors": "Authors",
"updated": "Updated"
},
"gdata-exporter": {
"uploading": "Uploading...",
"upload-error": "Upload error: ",
"new-spreadsheet": "A new Google spreadsheet",
"enter-spreadsheet": "Enter a name for the new Google spreadsheet",
"new-fusion": "A new Google Fusion table",
"enter-fusion": "Enter a name for the new Google Fusion table"
},
"gdata-auth": {
"authorize-label": "OpenRefine - Authorization",
"authorized-label": "Authorization process completed. Close this window and return to OpenRefine."
}
}

View File

@ -0,0 +1,56 @@
{
"gdata-import": {
"preparing": "In preparazione ...",
"creating": "Creazione il progetto ...",
"title": "Documenti Pubblici",
"import-by-url": "Importa un Google Spreadsheet o Fusion Table <em>pubblico</em> inserendo l'URL:",
"next->": "Avanti &raquo;",
"auth-doc": "Documenti Autorizzati",
"please": "Per piacere",
"sign-in": "autenticati ed autorizza",
"sign-out": "esci",
"access-data": "accedi ai tuoi dati Google.",
"retrieving": "Recuperando i documenti Google Doc ...",
"re-sign-in": "rieffettua l'autenticazione",
"another-account": "con un altro account"
},
"gdata-parsing": {
"start-over": "&laquo; Ricomincia",
"conf-pars": "Configura le opzioni per il parsing",
"proj-name": "Nome&nbsp;del&nbsp;progetto",
"create-proj": "Crea un progetto &raquo;",
"updating-preview": "Aggiornando la preview ...",
"worksheet": "Worksheets",
"option": "Opzioni",
"preview-button": "Aggiorna&nbsp;la&nbsp;Preview",
"ignore-first": "Ignora le prime",
"ignore": "linee all'inizio del file",
"parse-next": "Parsa le prossime",
"parse": "linee come nomi delle colonne",
"discard-next": "Scarta le prime",
"discard": "righe di dati",
"limit-next": "Carica al massimo",
"limit": "righe di dati",
"store-row": "Salva righe vuote",
"store-cell": "Salva le celle vuote come 'null'"
},
"gdata-source": {
"alert-url": "Devi specificare un indirizzo web (URL) per l'import.",
"type": "Tipo",
"title": "Titolo",
"authors": "Autori",
"updated": "Aggiornato"
},
"gdata-exporter": {
"uploading": "Caricando...",
"upload-error": "Errore durante il caricamento: ",
"new-spreadsheet": "Un nuovo Google spreadsheet",
"enter-spreadsheet": "Inserisci un nome per il nuovo Google spreadsheet",
"new-fusion": "Una nuova tabella Google Fusion",
"enter-fusion": "Inserisci un nome per la nuova tabella Google Fusion"
},
"gdata-auth": {
"authorize-label": "OpenRefine - Autorizzazione",
"authorized-label": "Processo di autorizzazione completato. Chiudi questa finestra e torna ad OpenRefine."
}
}

View File

@ -1,39 +1,39 @@
<div bind="wizardHeader" class="gdata-importing-wizard-header"><div class="grid-layout layout-tightest layout-full"><table><tr>
<td width="1%"><button bind="startOverButton" class="button">&laquo; Start Over</button></td>
<td width="98%">Configure Parsing Options</td>
<td style="text-align: right;">Project&nbsp;name</td>
<td width="98%" bind="gdata_conf_pars"></td>
<td style="text-align: right;" bind="gdata_proj_name"></td>
<td width="1%"><input class="inline" type="text" size="30" bind="projectNameInput" /></td>
<td width="1%"><button bind="createProjectButton" class="button button-primary">Create Project &raquo;</button></td>
<td width="1%"><button bind="createProjectButton" class="button button-primary"></button></td>
</tr></table></div></div>
<div bind="dataPanel" class="gdata-importing-parsing-data-panel"></div>
<div bind="progressPanel" class="gdata-importing-progress-data-panel">
<img src="images/large-spinner.gif" /> Updating preview ...
<img src="images/large-spinner.gif" /> <span bind="gdata-updating"></span>
</div>
<div bind="controlPanel" class="gdata-importing-parsing-control-panel"><div class="grid-layout layout-normal"><table>
<tr>
<td>Options</td>
<td><button class="button" bind="previewButton">Update&nbsp;Preview</button></td>
<td bind="gdata-options"></td>
<td><button class="button" bind="previewButton"></button></td>
</tr>
<tr>
<td><div class="grid-layout layout-tightest"><table>
<tr><td width="1%"><input type="checkbox" bind="skipCheckbox" id="$skip"/></td>
<td><label for="$skip">Discard initial</label></td>
<td><label for="$skip" bind="gdata_discard_next"></label></td>
<td><input bind="skipInput" type="text" class="lightweight" size="2" value="0" />
<label for="$skip">row(s) of data</label></td></tr>
<label for="$skip" bind="gdata_discard"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="limitCheckbox" id="$limit" /></td>
<td><label for="$limit">Load at most</label></td>
<td><label for="$limit" bind="gdata_limit_next"></label></td>
<td><input bind="limitInput" type="text" class="lightweight" size="2" value="0" />
<label for="$limit">row(s) of data</label></td></tr>
<label for="$limit" bind="gdata_limit"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="storeBlankRowsCheckbox" id="$store-blank-rows" /></td>
<td colspan="2"><label for="$store-blank-rows">Store blank rows</label></td></tr>
<td colspan="2"><label for="$store-blank-rows" bind="gdata_store_row"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="storeBlankCellsAsNullsCheckbox" id="$store-blank-cells" /></td>
<td colspan="2"><label for="$store-blank-cells">Store blank cells as nulls</label></td></tr>
<td colspan="2"><label for="$store-blank-cells" bind="gdata_store_cell"></label></td></tr>
</table></div></td>
</tr>
</table></div></div>

View File

@ -1,51 +1,51 @@
<div bind="wizardHeader" class="gdata-importing-wizard-header"><div class="grid-layout layout-tightest layout-full"><table><tr>
<td width="1%"><button bind="startOverButton" class="button">&laquo; Start Over</button></td>
<td width="98%">Configure Parsing Options</td>
<td style="text-align: right;">Project&nbsp;name</td>
<td width="1%"><button bind="startOverButton" class="button"></button></td>
<td width="98%" bind="gdata_conf_pars"></td>
<td style="text-align: right;" bind="gdata_proj_name"></td>
<td width="1%"><input class="inline" type="text" size="30" bind="projectNameInput" /></td>
<td width="1%"><button bind="createProjectButton" class="button button-primary">Create Project &raquo;</button></td>
<td width="1%"><button bind="createProjectButton" class="button button-primary"></button></td>
</tr></table></div></div>
<div bind="dataPanel" class="gdata-importing-parsing-data-panel"></div>
<div bind="progressPanel" class="gdata-importing-progress-data-panel">
<img src="images/large-spinner.gif" /> Updating preview ...
<img src="images/large-spinner.gif" /> <span bind="gdata-updating"></span>
</div>
<div bind="controlPanel" class="gdata-importing-parsing-control-panel"><div class="grid-layout layout-normal"><table>
<tr>
<td>Worksheets</td>
<td colspan="2">Options</td>
<td rowspan="2"><button class="button" bind="previewButton">Update&nbsp;Preview</button></td>
<td bind="gdata-worksheet"></td>
<td colspan="2" bind="gdata-options"></td>
<td rowspan="2"><button class="button" bind="previewButton"></button></td>
</tr>
<tr>
<td rowspan="2" width="40%"><div class="grid-layout layout-tightest"><table bind="sheetRecordContainer"></table></div></td>
<td colspan="2"><div class="grid-layout layout-tightest"><table>
<tr><td width="1%"><input type="checkbox" bind="ignoreCheckbox" id="$ignore" /></td>
<td><label for="$ignore">Ignore first</label></td>
<td><label for="$ignore" bind="gdata_ignore_first"></label></td>
<td><input bind="ignoreInput" type="text" class="lightweight" size="2" value="0" />
<label for="$ignore">line(s) at beginning of file</label></td></tr>
<label for="$ignore" bind="gdata_ignore"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="headerLinesCheckbox" id="$headers" /></td>
<td><label for="$headers">Parse next</label></td>
<td><label for="$headers" bind="gdata_parse_next"></label></td>
<td><input bind="headerLinesInput" type="text" class="lightweight" size="2" value="1" />
<label for="$headers">line(s) as column headers</label></td></tr>
<label for="$headers" bind="gdata_parse"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="skipCheckbox" id="$skip" /></td>
<td><label for="$skip">Discard initial</label></td>
<td><label for="$skip" bind="gdata_discard_next"></label></td>
<td><input bind="skipInput" type="text" class="lightweight" size="2" value="0" />
<label for="$skip">row(s) of data</label></td></tr>
<label for="$skip" bind="gdata_discard"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="limitCheckbox" id="$limit" /></td>
<td><label for="$limit">Load at most</label></td>
<td><label for="$limit" bind="gdata_limit_next"></label></td>
<td><input bind="limitInput" type="text" class="lightweight" size="2" value="0" />
<label for="$limit">row(s) of data</label></td></tr>
<label for="$limit" bind="gdata_limit"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="storeBlankRowsCheckbox" id="$store-blank-rows" /></td>
<td colspan="2"><label for="$store-blank-rows">Store blank rows</label></td></tr>
<td colspan="2"><label for="$store-blank-rows" bind="gdata_store_row"></label></td></tr>
<tr><td width="1%"><input type="checkbox" bind="storeBlankCellsAsNullsCheckbox" id="$store-blank-cells" /></td>
<td colspan="2"><label for="$store-blank-cells">Store blank cells as nulls</label></td></tr>
<td colspan="2"><label for="$store-blank-cells" bind="gdata_store_cell"></label></td></tr>
</table></div></td>
</tr>
</table></div></div>

View File

@ -41,6 +41,18 @@ Refine.GDataSourceUI.prototype.attachUI = function(body) {
this._body.html(DOM.loadHTML("gdata", "scripts/index/import-from-gdata-form.html"));
this._elmts = DOM.bind(this._body);
$('#gdata-title').text($.i18n._("gdata-import")["title"]);
$('#gdata-import').html($.i18n._("gdata-import")["import-by-url"]);
$('#gdata-next').html($.i18n._("gdata-import")["next->"]);
$('#gdata-auth-doc').text($.i18n._("gdata-import")["auth-doc"]);
$('#gdata-please').text($.i18n._("gdata-import")["please"]);
$('#gdata-signin-btn').text($.i18n._("gdata-import")["sign-in"]);
$('#gdata-access-data').text($.i18n._("gdata-import")["access-data"]);
$('#gdata-retrieving').text($.i18n._("gdata-import")["retrieving"]);
$('#gdata-retrieving').text($.i18n._("gdata-import")["sign-out"]);
$('#gdata-resignin').text($.i18n._("gdata-import")["re-sign-in"]);
$('#gdata-another-account').text($.i18n._("gdata-import")["another-account"]);
var self = this;
this._body.find('.gdata-signin.button').click(function() {
GdataExtension.showAuthorizationDialog(
@ -62,7 +74,7 @@ Refine.GDataSourceUI.prototype.attachUI = function(body) {
this._elmts.urlNextButton.click(function(evt) {
var url = $.trim(self._elmts.urlInput[0].value);
if (url.length === 0) {
window.alert("You must specify a web address (URL) to import.");
window.alert($.i18n._('gdata-source')["alert-url"]);
} else {
var doc = {};
doc.docSelfLink = url;
@ -112,10 +124,10 @@ Refine.GDataSourceUI.prototype._renderDocuments = function(o) {
var table = $(
'<table><tr>' +
'<th></th>' + // starred
'<th>Type</th>' +
'<th>Title</th>' +
'<th>Authors</th>' +
'<th>Updated</th>' +
'<th>'+$.i18n._('gdata-source')["type"]+'</th>' +
'<th>'+$.i18n._('gdata-source')["title"]+'</th>' +
'<th>'+$.i18n._('gdata-source')["authors"]+'</th>' +
'<th>'+$.i18n._('gdata-source')["updated"]+'</th>' +
'</tr></table>'
).appendTo(this._elmts.listingContainer)[0];

View File

@ -1,29 +1,29 @@
<div>
<div bind="publicDocsPanel" class="gdata-panel">
<h1>Public Documents</h1>
<h1 id="gdata-title"></h1>
<div class="grid-layout layout-tighter"><table>
<tr><td colspan="2">Import a <em>public</em> Google Spreadsheet or Fusion Table by its URL:</td></tr>
<tr><td colspan="2" id="gdata-import"></td></tr>
<tr bind="urlRow">
<td><input bind="urlInput" name="download" class="default-importing-web-url" /></td>
<td><button bind="urlNextButton" class="button button-primary" type="button">Next &raquo;</button></td>
<td><button bind="urlNextButton" class="button button-primary" type="button" id="gdata-next"></button></td>
</tr>
</table></div>
</div>
<div bind="authorizedDocsPanel" class="gdata-panel">
<h1>Authorized Documents</h1>
<h1 id="gdata-auth-doc"></h1>
<div bind="signinPage" class="gdata-page">
<p>Please <button class="gdata-signin button button-primary">sign in and authorize</button>
access to your Google data.</p>
<p><span id="gdata-please"></span> <button class="gdata-signin button button-primary" id="gdata-signin-btn"></button>
<span id="gdata-access-data"></p>
</div>
<div bind="progressPage" class="gdata-page">
<p><img src="images/large-spinner.gif" /> Retrieving Google Docs documents ...</p>
<p><img src="images/large-spinner.gif" /> <span id="gdata-retrieving"></span></p>
</div>
<div bind="listingPage" class="gdata-page grid-layout layout-normal"><table>
<tr>
<td width="%"><button class="gdata-signout button">sign out</button></td>
<td><button class="gdata-signin button">re-sign in</button> with another account</td>
<td width="%"><button class="gdata-signout button" id="gdata-signout"></button></td>
<td><button class="gdata-signin button" id="gdata-resignin"></button> <span id="gdata-another-account"></span></td>
</tr>
<tr><td colspan="2"><div bind="listingContainer" class="grid-layout layout-tight gdata-document-container"></div></td></tr>
</table></div>

View File

@ -31,6 +31,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
//Internationalization init
var lang = navigator.language.split("-")[0]
|| navigator.userLanguage.split("-")[0];
var dictionary = "";
$.ajax({
url : "/command/gdata/load-language?",
type : "POST",
async : false,
data : {
lng : lang
},
success : function(data) {
dictionary = data;
}
});
$.i18n.setDictionary(dictionary);
// End internationalization
Refine.GDataImportingController = function(createProjectUI) {
this._createProjectUI = createProjectUI;
@ -41,11 +59,14 @@ Refine.GDataImportingController = function(createProjectUI) {
id: "gdata-source",
ui: new Refine.GDataSourceUI(this)
});
$('#gdata-authorize').text($.i18n._('gdata-auth')["authorize-label"]);
$('#gdata-authorized').text($.i18n._('gdata-auth')["authorized-label"]);
};
Refine.CreateProjectUI.controllers.push(Refine.GDataImportingController);
Refine.GDataImportingController.prototype.startImportingDocument = function(doc) {
var dismiss = DialogSystem.showBusy("Preparing ...");
var dismiss = DialogSystem.showBusy($.i18n._('gdata-import')["preparing"]);
var self = this;
$.post(
@ -143,6 +164,27 @@ Refine.GDataImportingController.prototype._showParsingPanel = function() {
'scripts/index/gdata-parsing-panel.html'));
this._parsingPanelElmts = DOM.bind(this._parsingPanel);
if(this._doc.type != 'table'){
this._parsingPanelElmts.gdata-worksheet.html($.i18n._('gdata-parsing')["worksheet"]);
this._parsingPanelElmts.gdata_ignore_first.html($.i18n._('gdata-parsing')["ignore-first"]);
this._parsingPanelElmts.gdata_ignore.html($.i18n._('gdata-parsing')["ignore"]);
this._parsingPanelElmts.gdata_parse_next.html($.i18n._('gdata-parsing')["parse-next"]);
this._parsingPanelElmts.gdata_parse.html($.i18n._('gdata-parsing')["parse"]);
}
this._parsingPanelElmts.startOverButton.html($.i18n._('gdata-parsing')["start-over"]);
this._parsingPanelElmts.gdata_conf_pars.html($.i18n._('gdata-parsing')["conf-pars"]);
this._parsingPanelElmts.gdata_proj_name.html($.i18n._('gdata-parsing')["proj-name"]);
this._parsingPanelElmts.createProjectButton.html($.i18n._('gdata-parsing')["create-proj"]);
this._parsingPanelElmts.gdata-options.html($.i18n._('gdata-parsing')["option"]);
this._parsingPanelElmts.previewButton.html($.i18n._('gdata-parsing')["preview-button"]);
this._parsingPanelElmts.gdata-updating.html($.i18n._('gdata-parsing')["updating-preview"]);
this._parsingPanelElmts.gdata_discard_next.html($.i18n._('gdata-parsing')["discard-next"]);
this._parsingPanelElmts.gdata_discard.html($.i18n._('gdata-parsing')["discard"]);
this._parsingPanelElmts.gdata_limit_next.html($.i18n._('gdata-parsing')["limit-next"]);
this._parsingPanelElmts.gdata_limit.html($.i18n._('gdata-parsing')["limit"]);
this._parsingPanelElmts.gdata_store_row.html($.i18n._('gdata-parsing')["store-row"]);
this._parsingPanelElmts.gdata_store_cell.html($.i18n._('gdata-parsing')["store-cell"]);
if (this._parsingPanelResizer) {
$(window).unbind('resize', this._parsingPanelResizer);
}
@ -376,7 +418,7 @@ Refine.GDataImportingController.prototype._createProject = function() {
},
1000
);
self._createProjectUI.showImportProgressPanel("Creating project ...", function() {
self._createProjectUI.showImportProgressPanel($.i18n._('gdata-import')["creating"], function() {
// stop the timed polling
window.clearInterval(timerID);

View File

@ -31,12 +31,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var dictionary = "";
$.ajax({
url : "/command/gdata/load-language?",
type : "POST",
async : false,
data : {
lng : lang
},
success : function(data) {
dictionary = data;
}
});
$.i18n.setDictionary(dictionary);
// End internationalization
(function() {
var handleUpload = function(options, exportAllRows, onDone, prompt) {
var doUpload = function() {
var name = window.prompt(prompt, theProject.metadata.name);
if (name) {
var dismiss = DialogSystem.showBusy('Uploading...');
var dismiss = DialogSystem.showBusy($.i18n._('gdata-exporter')["uploading"]);
$.post(
"command/gdata/upload",
{
@ -52,7 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (o.url) {
window.open(o.url, '_blank');
} else {
alert('Upload error: ' + o.message)
alert($.i18n._('gdata-exporter')["upload-error"] + o.message)
}
onDone();
},
@ -70,16 +85,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
CustomTabularExporterDialog.uploadTargets.push({
id: 'gdata/google-spreadsheet',
label: 'A new Google spreadsheet',
label: $.i18n._('gdata-exporter')["new-spreadsheet"],
handler: function(options, exportAllRows, onDone) {
handleUpload(options, exportAllRows, onDone, 'Enter a name for the new Google spreadsheet');
handleUpload(options, exportAllRows, onDone, $.i18n._('gdata-exporter')["enter-spreadsheet"]);
}
});
CustomTabularExporterDialog.uploadTargets.push({
id: 'gdata/fusion-table',
label: 'A new Google Fusion table',
label: $.i18n._('gdata-exporter')["new-fusion"],
handler: function(options, exportAllRows, onDone) {
handleUpload(options, exportAllRows, onDone, 'Enter a name for the new Google Fusion table');
handleUpload(options, exportAllRows, onDone, $.i18n._('gdata-exporter')["enter-fusion"]);
}
});
})();

View File

@ -77,13 +77,7 @@ public class FusionTableImporter {
}
static void setProgress(ImportingJob job, String fileSource, int percent) {
JSONObject progress = JSONUtilities.getObject(job.config, "progress");
if (progress == null) {
progress = new JSONObject();
JSONUtilities.safePut(job.config, "progress", progress);
}
JSONUtilities.safePut(progress, "message", "Reading " + fileSource);
JSONUtilities.safePut(progress, "percent", percent);
job.setProgress(percent, "Reading " + fileSource);
}
@ -148,7 +142,7 @@ public class FusionTableImporter {
rowsOfCells = getRowsOfCells(newBatchRowStart);
batchRowStart = newBatchRowStart;
GDataImporter.setProgress(job, fileSource, -1 /* batchRowStart * 100 / totalRows */);
setProgress(job, fileSource, -1 /* batchRowStart * 100 / totalRows */);
}
if (rowsOfCells != null && nextRow - batchRowStart < rowsOfCells.size()) {

View File

@ -168,14 +168,8 @@ public class GDataImporter {
}
}
static void setProgress(ImportingJob job, String fileSource, int percent) {
JSONObject progress = JSONUtilities.getObject(job.config, "progress");
if (progress == null) {
progress = new JSONObject();
JSONUtilities.safePut(job.config, "progress", progress);
}
JSONUtilities.safePut(progress, "message", "Reading " + fileSource);
JSONUtilities.safePut(progress, "percent", percent);
static private void setProgress(ImportingJob job, String fileSource, int percent) {
job.setProgress(percent, "Reading " + fileSource);
}
static private class WorksheetBatchRowReader implements TableDataReader {

View File

@ -302,9 +302,6 @@ public class GDataImportingController implements ImportingController {
job.updating = true;
try {
// This is for setting progress during the parsing process.
job.config = new JSONObject();
JSONObject optionObj = ParsingUtilities.evaluateJsonStringToObject(
request.getParameter("options"));
@ -373,7 +370,7 @@ public class GDataImportingController implements ImportingController {
final List<Exception> exceptions = new LinkedList<Exception>();
JSONUtilities.safePut(job.config, "state", "creating-project");
job.setState("creating-project");
final Project project = new Project();
new Thread() {
@ -395,16 +392,14 @@ public class GDataImportingController implements ImportingController {
if (!job.canceled) {
if (exceptions.size() > 0) {
JSONUtilities.safePut(job.config, "errors",
DefaultImportingController.convertErrorsToJsonArray(exceptions));
JSONUtilities.safePut(job.config, "state", "error");
job.setError(exceptions);
} else {
project.update(); // update all internal models, indexes, caches, etc.
ProjectManager.singleton.registerProject(project, pm);
JSONUtilities.safePut(job.config, "state", "created-project");
JSONUtilities.safePut(job.config, "projectID", project.id);
job.setState("created-project");
job.setProjectID(project.id);
}
job.touch();

View File

@ -0,0 +1,74 @@
package com.google.refine.extension.gdata.commands;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.refine.ProjectManager;
import com.google.refine.commands.Command;
public class LoadLanguageCommand extends Command {
public LoadLanguageCommand() {
// TODO Auto-generated constructor stub
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String rawDirectoryFile = request.getSession().getServletContext()
.getRealPath("extensions/gdata/module/langs/");
String cleanedDirectory = rawDirectoryFile.replace("main" + File.separator + "webapp" + File.separator, "");
BufferedReader reader = null;
String param = null;
try {
param = (String) ProjectManager.singleton.getPreferenceStore().get("userLang");
} catch (NullPointerException e) {
}
if (param == null) param = request.getParameter("lng");
String[] langs = param.split(" ");
try {
String file = cleanedDirectory + File.separator + "translation-" + langs[0] + ".json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e1) {
try {
String file = cleanedDirectory + File.separator + "translation-default.json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e3) {
e3.printStackTrace();
}
}
String line = null;
String message = new String();
if (reader != null) {
while ((line = reader.readLine()) != null) {
// buffer.append(line);
message += line + System.getProperty("line.separator");
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(message);
response.getWriter().flush();
response.getWriter().close();
}
}

View File

@ -52,7 +52,7 @@
<target name="build_java">
<mkdir dir="${classes.dir}" />
<javac encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<javac source="${java_version}" target="${java_version}" encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<src path="${src.dir}"/>
<classpath refid="class.path" />
</javac>

View File

@ -53,7 +53,7 @@
<target name="build_java">
<mkdir dir="${classes.dir}" />
<javac encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<javac source="${java_version}" target="${java_version}" encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<src path="${src.dir}"/>
<classpath refid="class.path" />
</javac>

View File

@ -57,7 +57,7 @@
<target name="build_java">
<mkdir dir="${classes.dir}" />
<javac encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<javac source="${java_version}" target="${java_version}" encoding="utf-8" destdir="${classes.dir}" debug="true" includeAntRuntime="no">
<src path="${src.dir}"/>
<classpath refid="class.path" />
</javac>

View File

@ -172,7 +172,7 @@ public class Engine implements Jsonizable {
throw new InternalError("This method should not be called when the engine is not in record mode.");
}
public void initializeFromJSON(JSONObject o) throws Exception {
public void initializeFromJSON(JSONObject o) throws JSONException {
if (o == null) {
return;
}

View File

@ -41,13 +41,30 @@ import com.google.refine.model.Row;
* particular criteria, such as facets' constraints.
*/
public interface RowVisitor {
public void start(Project project); // called before any visit() call
/**
* Called before any visit() call.
*
* @param project
*/
public void start(Project project);
/**
* @param project project
* @param rowIndex zero-based row index
* @param row row
* @return true to abort visitation early - no further visit calls will be made
*/
public boolean visit(
Project project,
int rowIndex, // zero-based row index
int rowIndex,
Row row
);
public void end(Project project); // called after all visit() calls
/**
* Called after all visit() calls.
*
* @param project
*/
public void end(Project project);
}

View File

@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.browsing.facets;
import org.json.JSONException;
import org.json.JSONObject;
import com.google.refine.Jsonizable;
@ -54,5 +55,5 @@ public interface Facet extends Jsonizable {
public void computeChoices(Project project, FilteredRecords filteredRecords);
public void initializeFromJSON(Project project, JSONObject o) throws Exception;
public void initializeFromJSON(Project project, JSONObject o) throws JSONException;
}

View File

@ -152,7 +152,7 @@ public class ListFacet implements Facet {
}
@Override
public void initializeFromJSON(Project project, JSONObject o) throws Exception {
public void initializeFromJSON(Project project, JSONObject o) throws JSONException {
_name = o.getString("name");
_expression = o.getString("expression");
_columnName = o.getString("columnName");

View File

@ -159,7 +159,7 @@ public class RangeFacet implements Facet {
}
@Override
public void initializeFromJSON(Project project, JSONObject o) throws Exception {
public void initializeFromJSON(Project project, JSONObject o) throws JSONException {
_name = o.getString("name");
_expression = o.getString("expression");
_columnName = o.getString("columnName");

View File

@ -206,7 +206,7 @@ public class ScatterplotFacet implements Facet {
}
@Override
public void initializeFromJSON(Project project, JSONObject o) throws Exception {
public void initializeFromJSON(Project project, JSONObject o) throws JSONException {
name = o.getString(NAME);
l = size = (o.has(SIZE)) ? o.getInt(SIZE) : 100;
dot = (o.has(DOT)) ? o.getInt(DOT) : 0.5d;

View File

@ -84,7 +84,7 @@ public class TextSearchFacet implements Facet {
}
@Override
public void initializeFromJSON(Project project, JSONObject o) throws Exception {
public void initializeFromJSON(Project project, JSONObject o) throws JSONException {
_name = o.getString("name");
_columnName = o.getString("columnName");

View File

@ -111,7 +111,7 @@ public class TimeRangeFacet extends RangeFacet {
}
@Override
public void initializeFromJSON(Project project, JSONObject o) throws Exception {
public void initializeFromJSON(Project project, JSONObject o) throws JSONException {
_name = o.getString("name");
_expression = o.getString("expression");
_columnName = o.getString("columnName");

View File

@ -50,6 +50,7 @@ import com.google.refine.model.Cell;
import com.google.refine.model.Project;
import com.google.refine.model.Record;
import com.google.refine.model.Row;
import com.google.refine.util.StringUtils;
/**
* Visit matched rows or records and group them into facet choices based on the values computed
@ -174,7 +175,7 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
if (ExpressionUtils.isError(value)) {
hasError = true;
} else if (ExpressionUtils.isNonBlankData(value)) {
String valueString = value.toString();
String valueString = StringUtils.toString(value);
IndexedNominalFacetChoice facetChoice = choices.get(valueString);
if (facetChoice != null) {
@ -236,7 +237,7 @@ public class ExpressionNominalValueGrouper implements RowVisitor, RecordVisitor
if (ExpressionUtils.isError(choiceValue)) {
return errorCount;
} else if (ExpressionUtils.isNonBlankData(choiceValue)) {
IndexedNominalFacetChoice choice = choices.get(choiceValue);
IndexedNominalFacetChoice choice = choices.get(StringUtils.toString(choiceValue));
return choice != null ? choice.count : 0;
} else {
return blankCount;

View File

@ -41,13 +41,17 @@ import org.apache.commons.lang.StringUtils;
public class FingerprintKeyer extends Keyer {
static final Pattern alphanum = Pattern.compile("\\p{Punct}|\\p{Cntrl}");
// Punctuation and control characters (except for TAB which we need for split to work)
static final Pattern punctctrl = Pattern.compile("\\p{Punct}|[\\x00-\\x08\\x0A-\\x1F\\x7F]");
@Override
public String key(String s, Object... o) {
if (s == null || o !=null && o.length > 0) {
throw new IllegalArgumentException("Fingerprint keyer accepts a single string parameter");
}
s = s.trim(); // first off, remove whitespace around the string
s = s.toLowerCase(); // then lowercase it
s = alphanum.matcher(s).replaceAll(""); // then remove all punctuation and control chars
s = punctctrl.matcher(s).replaceAll(""); // then remove all punctuation and control chars
String[] frags = StringUtils.split(s); // split by whitespace
TreeSet<String> set = new TreeSet<String>();
for (String ss : frags) {
@ -57,7 +61,9 @@ public class FingerprintKeyer extends Keyer {
Iterator<String> i = set.iterator();
while (i.hasNext()) { // join ordered fragments back together
b.append(i.next());
b.append(' ');
if (i.hasNext()) {
b.append(' ');
}
}
return asciify(b.toString()); // find ASCII equivalent to characters
}

View File

@ -0,0 +1,73 @@
package com.google.refine.commands.lang;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.refine.ProjectManager;
import com.google.refine.commands.Command;
public class LoadLanguageCommand extends Command {
public LoadLanguageCommand() {
// TODO Auto-generated constructor stub
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String rawDirectoryFile = request.getSession().getServletContext().getRealPath("webapp/modules/langs/");
String cleanedDirectory = rawDirectoryFile.replace("main" + File.separator + "webapp" + File.separator, "main"
+ File.separator);
BufferedReader reader = null;
String param = null;
try {
param = (String) ProjectManager.singleton.getPreferenceStore().get("userLang");
} catch (NullPointerException e) {
}
if (param == null) param = request.getParameter("lng");
String[] langs = param.split(" ");
try {
String file = cleanedDirectory + File.separator + "translation-" + langs[0] + ".json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e1) {
try {
String file = cleanedDirectory + File.separator + "translation-default.json";
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
} catch (FileNotFoundException e3) {
e3.printStackTrace();
}
}
String line = null;
String message = new String();
if (reader != null) {
while ((line = reader.readLine()) != null) {
// buffer.append(line);
message += line + System.getProperty("line.separator");
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json");
response.getWriter().println(message);
response.getWriter().flush();
response.getWriter().close();
}
}

View File

@ -0,0 +1,33 @@
package com.google.refine.commands.lang;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.refine.ProjectManager;
import com.google.refine.commands.Command;
import com.google.refine.preference.PreferenceStore;
public class SetLanguageCommand extends Command {
public SetLanguageCommand() {
// TODO Auto-generated constructor stub
}
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String lang = request.getParameter("lng");
PreferenceStore pref = ProjectManager.singleton.getPreferenceStore();
pref.put("userLang", lang);
}
}

View File

@ -112,7 +112,7 @@ public class CreateProjectCommand extends Command {
} else {
Format formatRecord = ImportingManager.formatToRecord.get(format);
optionObj = formatRecord.parser.createParserUIInitializationData(
job, ImportingUtilities.getSelectedFileRecords(job), format);
job, job.getSelectedFileRecords(), format);
}
adjustLegacyOptions(format, parameters, optionObj);

View File

@ -42,33 +42,33 @@ import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.Function;
import com.google.refine.util.StringUtils;
public class ToString implements Function {
@Override
public String call(Properties bindings, Object[] args) {
public Object call(Properties bindings, Object[] args) {
if (args.length >= 1) {
Object o1 = args[0];
if (o1 != null) {
if (args.length == 2) {
if (o1 instanceof Calendar || o1 instanceof Date) {
DateFormat formatter = null;
if (args.length == 2) {
Object o2 = args[1];
if (o2 != null && o2 instanceof String) {
formatter = new SimpleDateFormat((String) o2);
}
Object o2 = args[1];
if (o2 instanceof String) {
DateFormat formatter = new SimpleDateFormat((String) o2);
return formatter.format(o1 instanceof Date ? ((Date) o1) : ((Calendar) o1).getTime());
}
if (formatter == null) {
formatter = DateFormat.getDateInstance();
}
return formatter.format(o1 instanceof Date ? ((Date) o1) : ((Calendar) o1).getTime());
} else {
return (o1 instanceof String) ? (String) o1 : o1.toString();
}
} else if (args.length == 1) {
if (o1 instanceof String) {
return (String) o1;
} else if (o1 != null) {
return StringUtils.toString(o1);
}
}
}
return null;
return new EvalError("ToString accepts an object an optional second argument containing a date format string");
}

View File

@ -38,18 +38,23 @@ import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
public class And implements Function {
@Override
public Object call(Properties bindings, Object[] args) {
for (Object o : args) {
if (!Not.objectToBoolean(o)) {
return false;
if (args.length == 2 && args[0] instanceof Boolean && args[1] instanceof Boolean) {
for (Object o : args) {
if (!Not.objectToBoolean(o)) {
return false;
}
}
return true;
}
return true;
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects two booleans");
}
@Override

View File

@ -46,7 +46,7 @@ public class Not implements Function {
@Override
public Object call(Properties bindings, Object[] args) {
if (args.length == 1) {
if (args.length == 1 && args[0] instanceof Boolean) {
return !objectToBoolean(args[0]);
}
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects a boolean");

View File

@ -38,18 +38,23 @@ import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
public class Or implements Function {
@Override
public Object call(Properties bindings, Object[] args) {
for (Object o : args) {
if (Not.objectToBoolean(o)) {
return true;
if (args.length == 2 && args[0] instanceof Boolean && args[1] instanceof Boolean) {
for (Object o : args) {
if (Not.objectToBoolean(o)) {
return true;
}
}
return false;
}
return false;
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects two booleans");
}
@Override

View File

@ -0,0 +1,60 @@
/*
Copyright (c) 2013, Jesus M. Castagnetto
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine.expr.functions.booleans;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
public class Xor implements Function {
@Override
public Object call(Properties bindings, Object[] args) {
if (args.length == 2 && args[0] instanceof Boolean && args[1] instanceof Boolean) {
return (Boolean) args[0] ^ (Boolean) args[1];
}
return new EvalError(ControlFunctionRegistry.getFunctionName(this) + " expects 2 booleans");
}
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("description");
writer.value("XORs two boolean values");
writer.key("params");
writer.value("boolean a, boolean b");
writer.key("returns");
writer.value("boolean");
writer.endObject();
}
}

View File

@ -42,9 +42,9 @@ import org.json.JSONException;
import org.json.JSONWriter;
import com.google.refine.expr.EvalError;
import com.google.refine.expr.functions.ToString;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
import com.google.refine.util.StringUtils;
public class Escape implements Function {
@ -60,8 +60,7 @@ public class Escape implements Function {
s = "";
} else {
// Use our own ToString so that formatting is consistent
ToString toString = new ToString();
s = toString.call(bindings,new Object[] {o1});
s = StringUtils.toString(o1);
}
if (o2 instanceof String) {
String mode = ((String) o2).toLowerCase();

View File

@ -56,6 +56,7 @@ import com.google.refine.expr.functions.arrays.Uniques;
import com.google.refine.expr.functions.booleans.And;
import com.google.refine.expr.functions.booleans.Not;
import com.google.refine.expr.functions.booleans.Or;
import com.google.refine.expr.functions.booleans.Xor;
import com.google.refine.expr.functions.date.DatePart;
import com.google.refine.expr.functions.date.Inc;
import com.google.refine.expr.functions.date.Now;
@ -284,6 +285,7 @@ public class ControlFunctionRegistry {
registerFunction("and", new And());
registerFunction("or", new Or());
registerFunction("not", new Not());
registerFunction("xor", new Xor());
registerFunction("cross", new Cross());

View File

@ -209,10 +209,8 @@ public class ImporterUtilities {
long totalBytesRead = 0;
void setProgress(String fileSource, long bytesRead) {
ImportingUtilities.setCreatingProjectProgress(
job,
"Reading " + fileSource,
totalSize2 == 0 ? -1 : (int) (100 * (totalBytesRead + bytesRead) / totalSize2));
job.setProgress(totalSize2 == 0 ? -1 : (int) (100 * (totalBytesRead + bytesRead) / totalSize2),
"Reading " + fileSource);
}
@Override

View File

@ -228,7 +228,7 @@ public class DefaultImportingController implements ImportingController {
Format formatRecord = ImportingManager.formatToRecord.get(format);
if (formatRecord != null && formatRecord.parser != null) {
JSONObject options = formatRecord.parser.createParserUIInitializationData(
job, ImportingUtilities.getSelectedFileRecords(job), format);
job, job.getSelectedFileRecords(), format);
JSONObject result = new JSONObject();
JSONUtilities.safePut(result, "status", "ok");
JSONUtilities.safePut(result, "options", options);

View File

@ -35,9 +35,12 @@ package com.google.refine.importing;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.FileUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONWriter;
@ -52,7 +55,7 @@ public class ImportingJob implements Jsonizable {
final public long id;
final public File dir; // Temporary directory where the data about this job is stored
public JSONObject config = null;
private JSONObject config;
public Project project;
public ProjectMetadata metadata;
@ -61,22 +64,101 @@ public class ImportingJob implements Jsonizable {
public boolean updating;
public boolean canceled;
final private Object lock = new Object();
public ImportingJob(long id, File dir) {
this.id = id;
this.dir = dir;
JSONObject cfg = new JSONObject();
JSONUtilities.safePut(cfg, "state", "new");
JSONUtilities.safePut(cfg, "hasData", false);
this.config = cfg;
dir.mkdirs();
}
public JSONObject getOrCreateDefaultConfig() {
if (config == null) {
config = new JSONObject();
JSONUtilities.safePut(config, "state", "new");
JSONUtilities.safePut(config, "hasData", false);
}
return config;
}
public void setState(String state) {
synchronized(config) {
JSONUtilities.safePut(config, "state", state);
}
}
public void setError(List<Exception> exceptions) {
synchronized(config) {
JSONUtilities.safePut(config, "errors",
DefaultImportingController.convertErrorsToJsonArray(exceptions));
setState("error");
}
}
public void setProjectID(long id2) {
synchronized (config) {
JSONUtilities.safePut(config, "projectID", project.id);
}
}
public void setProgress(int percent, String message) {
synchronized (config) {
JSONObject progress = JSONUtilities.getObject(config, "progress");
if (progress == null) {
progress = new JSONObject();
JSONUtilities.safePut(config, "progress", progress);
}
JSONUtilities.safePut(progress, "message", message);
JSONUtilities.safePut(progress, "percent", percent);
JSONUtilities.safePut(progress, "memory", Runtime.getRuntime().totalMemory() / 1000000);
JSONUtilities.safePut(progress, "maxmemory", Runtime.getRuntime().maxMemory() / 1000000);
}
}
public void setFileSelection(JSONArray fileSelectionArray) {
synchronized (config) {
JSONUtilities.safePut(config, "fileSelection", fileSelectionArray);
}
}
public void setRankedFormats(JSONArray rankedFormats) {
synchronized (config) {
JSONUtilities.safePut(config, "rankedFormats", rankedFormats);
}
}
public JSONObject getRetrievalRecord() {
synchronized(config) {
return JSONUtilities.getObject(config,"retrievalRecord");
}
}
public List<JSONObject> getSelectedFileRecords() {
List<JSONObject> results = new ArrayList<JSONObject>();
JSONObject retrievalRecord = JSONUtilities.getObject(config,"retrievalRecord");
if (retrievalRecord != null) {
JSONArray fileRecordArray = JSONUtilities.getArray(retrievalRecord, "files");
if (fileRecordArray != null) {
JSONArray fileSelectionArray = JSONUtilities.getArray(config,"fileSelection");
if (fileSelectionArray != null) {
for (int i = 0; i < fileSelectionArray.length(); i++) {
int index = JSONUtilities.getIntElement(fileSelectionArray, i, -1);
if (index >= 0 && index < fileRecordArray.length()) {
results.add(JSONUtilities.getObjectElement(fileRecordArray, index));
}
}
}
}
}
return results;
}
public void touch() {
lastTouched = System.currentTimeMillis();
}
@ -111,8 +193,12 @@ public class ImportingJob implements Jsonizable {
@Override
public void write(JSONWriter writer, Properties options)
throws JSONException {
writer.object();
writer.key("config"); writer.value(config);
writer.endObject();
synchronized(lock) {
writer.object();
writer.key("config"); writer.value(config);
writer.endObject();
}
}
}

View File

@ -44,6 +44,7 @@ import java.util.Properties;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.io.FileUtils;
import org.json.JSONException;
@ -82,7 +83,7 @@ public class ImportingManager {
static private RefineServlet servlet;
static private File importDir;
final static private Map<Long, ImportingJob> jobs = new HashMap<Long, ImportingJob>();
final static private Map<Long, ImportingJob> jobs = new ConcurrentHashMap<Long, ImportingJob>();
// Mapping from format to label, e.g., "text" to "Text files", "text/xml" to "XML files"
final static public Map<String, Format> formatToRecord = new HashMap<String, Format>();
@ -288,12 +289,11 @@ public class ImportingManager {
static private void cleanUpStaleJobs() {
long now = System.currentTimeMillis();
for (Long id : new HashSet<Long>(jobs.keySet())) {
for (Long id : jobs.keySet()) {
ImportingJob job = jobs.get(id);
if (job != null && !job.updating && now - job.lastTouched > s_stalePeriod) {
job.dispose();
jobs.remove(id);
logger.info("Disposed " + id);
}
}

View File

@ -147,14 +147,14 @@ public class ImportingUtilities {
}
static public void updateJobWithNewFileSelection(ImportingJob job, JSONArray fileSelectionArray) {
JSONUtilities.safePut(job.config, "fileSelection", fileSelectionArray);
job.setFileSelection(fileSelectionArray);
String bestFormat = ImportingUtilities.getCommonFormatForSelectedFiles(job, fileSelectionArray);
bestFormat = ImportingUtilities.guessBetterFormat(job, bestFormat);
JSONArray rankedFormats = new JSONArray();
JSONUtilities.safePut(job.config, "rankedFormats", rankedFormats);
ImportingUtilities.rankFormats(job, bestFormat, rankedFormats);
job.setRankedFormats(rankedFormats);
}
static public void retrieveContentFromPostRequest(
@ -210,6 +210,7 @@ public class ImportingUtilities {
}
});
@SuppressWarnings("rawtypes")
List tempFiles = upload.parseRequest(request);
progress.setProgress("Uploading data ...", -1);
@ -747,7 +748,7 @@ public class ImportingUtilities {
}
static public String getCommonFormatForSelectedFiles(ImportingJob job, JSONArray fileSelectionIndexes) {
JSONObject retrievalRecord = JSONUtilities.getObject(job.config, "retrievalRecord");
JSONObject retrievalRecord = job.getRetrievalRecord();
final Map<String, Integer> formatToCount = new HashMap<String, Integer>();
List<String> formats = new ArrayList<String>();
@ -780,7 +781,7 @@ public class ImportingUtilities {
}
static String guessBetterFormat(ImportingJob job, String bestFormat) {
JSONObject retrievalRecord = JSONUtilities.getObject(job.config, "retrievalRecord");
JSONObject retrievalRecord = job.getRetrievalRecord();
return retrievalRecord != null ? guessBetterFormat(job, retrievalRecord, bestFormat) : bestFormat;
}
@ -879,27 +880,7 @@ public class ImportingUtilities {
JSONUtilities.append(rankedFormats, format);
}
}
static public List<JSONObject> getSelectedFileRecords(ImportingJob job) {
List<JSONObject> results = new ArrayList<JSONObject>();
JSONObject retrievalRecord = JSONUtilities.getObject(job.config, "retrievalRecord");
if (retrievalRecord != null) {
JSONArray fileRecordArray = JSONUtilities.getArray(retrievalRecord, "files");
if (fileRecordArray != null) {
JSONArray fileSelectionArray = JSONUtilities.getArray(job.config, "fileSelection");
if (fileSelectionArray != null) {
for (int i = 0; i < fileSelectionArray.length(); i++) {
int index = JSONUtilities.getIntElement(fileSelectionArray, i, -1);
if (index >= 0 && index < fileRecordArray.length()) {
results.add(JSONUtilities.getObjectElement(fileRecordArray, index));
}
}
}
}
}
return results;
}
static public void previewParse(ImportingJob job, String format, JSONObject optionObj, List<Exception> exceptions) {
Format record = ImportingManager.formatToRecord.get(format);
@ -914,7 +895,7 @@ public class ImportingUtilities {
job.project,
job.metadata,
job,
getSelectedFileRecords(job),
job.getSelectedFileRecords(),
format,
100,
optionObj,
@ -936,7 +917,7 @@ public class ImportingUtilities {
return -1;
}
JSONUtilities.safePut(job.config, "state", "creating-project");
job.setState("creating-project");
final Project project = new Project();
if (synchronous) {
@ -975,7 +956,7 @@ public class ImportingUtilities {
project,
pm,
job,
getSelectedFileRecords(job),
job.getSelectedFileRecords(),
format,
-1,
optionObj,
@ -988,27 +969,15 @@ public class ImportingUtilities {
ProjectManager.singleton.registerProject(project, pm);
JSONUtilities.safePut(job.config, "projectID", project.id);
JSONUtilities.safePut(job.config, "state", "created-project");
job.setProjectID(project.id);
job.setState("created-project");
} else {
JSONUtilities.safePut(job.config, "state", "error");
JSONUtilities.safePut(job.config, "errors",
DefaultImportingController.convertErrorsToJsonArray(exceptions));
job.setError(exceptions);
}
job.touch();
job.updating = false;
}
}
static public void setCreatingProjectProgress(ImportingJob job, String message, int percent) {
JSONObject progress = JSONUtilities.getObject(job.config, "progress");
if (progress == null) {
progress = new JSONObject();
JSONUtilities.safePut(job.config, "progress", progress);
}
JSONUtilities.safePut(progress, "message", message);
JSONUtilities.safePut(progress, "percent", percent);
JSONUtilities.safePut(progress, "memory", Runtime.getRuntime().totalMemory() / 1000000);
JSONUtilities.safePut(progress, "maxmemory", Runtime.getRuntime().maxMemory() / 1000000);
}
}

View File

@ -74,6 +74,9 @@ public class ColumnModel implements Jsonizable {
return _maxCellIndex;
}
/**
* @return the next available cell index
*/
synchronized public int allocateNewCellIndex() {
return ++_maxCellIndex;
}
@ -287,4 +290,13 @@ public class ColumnModel implements Jsonizable {
_columnNames.add(column.getName());
}
}
/**
* Clear cached value computations for all columns
*/
public void clearPrecomputes() {
for (Column column : columns) {
column.clearPrecomputes();
}
}
}

View File

@ -40,6 +40,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import com.google.refine.ProjectManager;
import com.google.refine.history.Change;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
@ -60,6 +61,9 @@ public class MassRowChange implements Change {
project.rows.clear();
project.rows.addAll(_newRows);
project.columnModel.clearPrecomputes();
ProjectManager.singleton.getInterProjectModel().flushJoinsInvolvingProject(project.id);
project.update();
}
}

View File

@ -40,6 +40,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import com.google.refine.ProjectManager;
import com.google.refine.history.Change;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
@ -70,6 +71,9 @@ public class RowRemovalChange implements Change {
offset--;
}
project.columnModel.clearPrecomputes();
ProjectManager.singleton.getInterProjectModel().flushJoinsInvolvingProject(project.id);
project.update();
}
}

View File

@ -90,6 +90,7 @@ abstract public class ReconConfig implements Jsonizable {
mode = "core/" + mode;
}
// TODO: This can fail silently if the Freebase extension is not installed.
List<Class<? extends ReconConfig>> classes = s_opNameToClass.get(mode);
if (classes != null && classes.size() > 0) {
Class<? extends ReconConfig> klass = classes.get(classes.size() - 1);

View File

@ -40,6 +40,8 @@ import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
@ -250,6 +252,10 @@ public class StandardReconConfig extends ReconConfig {
jsonWriter.key("id"); jsonWriter.value(cell2.recon.match.id);
jsonWriter.key("name"); jsonWriter.value(cell2.recon.match.name);
jsonWriter.endObject();
} else if (cell2.value instanceof Calendar) {
jsonWriter.value(ParsingUtilities.dateToString(((Calendar) cell2.value).getTime()));
} else if (cell2.value instanceof Date) {
jsonWriter.value(ParsingUtilities.dateToString((Date) cell2.value));
} else {
jsonWriter.value(cell2.value.toString());
}

View File

@ -160,7 +160,8 @@ public class KeyValueColumnizeOperation extends AbstractOperation {
String keyString = key.toString();
// Start a new row on our beginning of record key
if (keyString.equals(recordKey)) {
// TODO: Add support for processing in record mode instead of just by rows
if (keyString.equals(recordKey) || recordKey == null) {
reusableRow = new Row(newColumns.size());
newRows.add(reusableRow);
currentRows.clear();

View File

@ -222,6 +222,7 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat
List<CellAtRow> responseBodies = new ArrayList<CellAtRow>(urls.size());
for (int i = 0; i < urls.size(); i++) {
CellAtRow urlData = urls.get(i);
long start = System.currentTimeMillis();
CellAtRow cellAtRow = fetch(urlData);
if (cellAtRow != null) {
responseBodies.add(cellAtRow);
@ -229,7 +230,10 @@ public class ColumnAdditionByFetchingURLsOperation extends EngineDependentOperat
_progress = i * 100 / urls.size();
try {
Thread.sleep(_delay);
long delay = _delay - (System.currentTimeMillis() - start);
if (delay > 0) {
Thread.sleep(delay);
}
} catch (InterruptedException e) {
if (_canceled) {
break;

View File

@ -75,6 +75,13 @@ abstract public class Criterion {
}
}
// TODO: We'd like things to be more strongly typed a la the following, but
// it's too involved to change right now
// abstract public class Key implements Comparable<Key> {
// abstract public int compareTo(Key key);
// }
abstract public class KeyMaker {
public Object makeKey(Project project, Record record) {
Object error = null;

View File

@ -33,6 +33,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.refine.sorting;
import java.text.CollationKey;
import java.text.Collator;
import org.json.JSONException;
@ -70,13 +71,13 @@ public class StringCriterion extends Criterion {
return new KeyMaker() {
@Override
protected Object makeKey(Object value) {
return (ExpressionUtils.isNonBlankData(value) && !(value instanceof String)) ?
value.toString() : value;
return collator.getCollationKey((ExpressionUtils.isNonBlankData(value)
&& !(value instanceof String)) ? value.toString() : (String) value);
}
@Override
public int compareKeys(Object key1, Object key2) {
return collator.compare(key1, key2);
return ((CollationKey)key1).compareTo((CollationKey)key2);
}
};
}

View File

@ -48,12 +48,18 @@ public class Parser {
int start = 0, current = 0;
while (current < s.length() - 1) {
char c = s.charAt(current);
char c2 = s.charAt(current + 1);
if (c == '\\') {
current += 2;
if (c2 == '\\' || c2 == '{' || c2 == '$') {
fragments.add(new StaticFragment(s.substring(start, current).concat(Character.toString(c2))));
start = current += 2;
} else {
// Invalid escape - just leave it in the template
current += 1;
}
continue;
}
char c2 = s.charAt(current + 1);
if (c == '$' && c2 == '{') {
int closeBrace = s.indexOf('}', current + 2);
if (closeBrace > current + 1) {

View File

@ -54,7 +54,7 @@ import org.json.JSONTokener;
public class ParsingUtilities {
static final public SimpleDateFormat s_sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static final public SimpleDateFormat ISO8601_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
static public Properties parseUrlParameters(HttpServletRequest request) {
Properties options = new Properties();
@ -136,6 +136,9 @@ public class ParsingUtilities {
}
private static final URLCodec codec = new URLCodec();
/**
* Encode a string as UTF-8.
*/
static public String encode(String s) {
try {
return codec.encode(s, "UTF-8");
@ -143,6 +146,10 @@ public class ParsingUtilities {
return s; // should not happen
}
}
/**
* Decode a string from UTF-8 encoding.
*/
static public String decode(String s) {
try {
return codec.decode(s, "UTF-8");
@ -153,13 +160,25 @@ public class ParsingUtilities {
}
}
/**
* Convert a date/time to an ISO 8601 string
*
* @param d the date to be written
* @return string with ISO 8601 formatted date & time
*/
static public String dateToString(Date d) {
return s_sdf.format(d);
return ISO8601_FORMAT.format(d);
}
/**
* Parse an ISO 8601 formatted string into a Java Date.
*
* @param s the string to be parsed
* @return Date or null if the parse failed
*/
static public Date stringToDate(String s) {
try {
return s_sdf.parse(s);
return ISO8601_FORMAT.parse(s);
} catch (ParseException e) {
return null;
}

View File

@ -0,0 +1,24 @@
package com.google.refine.util;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.Date;
public class StringUtils {
/**
* String formatting method that knows how to format dates (using the defaul locale's date formatter)
* @param o object to be converted to a string
* @return string representing object
*/
public static String toString(Object o) {
if (o instanceof Calendar || o instanceof Date) {
DateFormat formatter = DateFormat.getDateInstance();
return formatter.format(o instanceof Date ? ((Date) o) : ((Calendar) o).getTime());
} else {
return o.toString();
}
}
}

Binary file not shown.

View File

@ -0,0 +1,144 @@
/*
Copyright 2013, Thomas F. Morris
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine.tests.expr.functions;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.browsing.Engine;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Cell;
import com.google.refine.model.Column;
import com.google.refine.model.ModelException;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class FunctionTests extends RefineTest {
static Properties bindings;
Project project;
Properties options;
JSONObject engine_config;
Engine engine;
@Override
@BeforeTest
public void init() {
logger = LoggerFactory.getLogger(this.getClass());
}
@BeforeMethod
public void SetUp() throws IOException, ModelException {
bindings = new Properties();
File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir");
FileProjectManager.initialize(dir);
project = new Project();
ProjectMetadata pm = new ProjectMetadata();
pm.setName("TNG Test Project");
ProjectManager.singleton.registerProject(project, pm);
int index = project.columnModel.allocateNewCellIndex();
Column column = new Column(index,"Column A");
project.columnModel.addColumn(index, column, true);
options = mock(Properties.class);
bindings.put("project", project);
// Five rows of a's and five of 1s
for (int i = 0; i < 10; i++) {
Row row = new Row(1);
row.setCell(0, new Cell(i < 5 ? "a":new Integer(1), null));
project.rows.add(row);
}
}
@AfterMethod
public void TearDown() {
bindings = null;
}
/**
* Lookup a control function by name and invoke it with a variable number of args
*/
private static Object invoke(String name,Object... args) {
// registry uses static initializer, so no need to set it up
Function function = ControlFunctionRegistry.getFunction(name);
if (function == null) {
throw new IllegalArgumentException("Unknown function "+name);
}
if (args == null) {
return function.call(bindings,new Object[0]);
} else {
return function.call(bindings,args);
}
}
@Test
public void testInvalidParams() {
Assert.assertTrue(invoke("facetCount") instanceof EvalError);
Assert.assertTrue(invoke("facetCount", "one","two","three") instanceof EvalError);
Assert.assertTrue(invoke("facetCount", "one","bad(","Column A") instanceof EvalError);
}
@Test
public void testFacetCount() {
Assert.assertEquals(invoke("facetCount", "a", "value", "Column A"),Integer.valueOf(5));
Assert.assertEquals(invoke("facetCount", new Integer(1), "value", "Column A"),Integer.valueOf(5));
Assert.assertEquals(invoke("facetCount", new Integer(2), "value+1", "Column A"),Integer.valueOf(5));
}
}

View File

@ -0,0 +1,178 @@
/*
Copyright 2013, Thomas F. Morris
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine.tests.expr.functions.booleans;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.browsing.Engine;
import com.google.refine.expr.EvalError;
import com.google.refine.grel.ControlFunctionRegistry;
import com.google.refine.grel.Function;
import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Cell;
import com.google.refine.model.Column;
import com.google.refine.model.ModelException;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class BooleanTests extends RefineTest {
private static String TRUTH_TABLE[][] = {
{"and","true","true","true"},
{"and","false","false","false"},
{"and","true","false","false"},
{"and","false","true","false"},
{"or","true","true","true"},
{"or","false","false","false"},
{"or","true","false","true"},
{"or","false","true","true"},
{"xor","true","true","false"},
{"xor","false","false","false"},
{"xor","true","false","true"},
{"xor","false","true","true"},
};
static Properties bindings;
Project project;
Properties options;
JSONObject engine_config;
Engine engine;
@Override
@BeforeTest
public void init() {
logger = LoggerFactory.getLogger(this.getClass());
}
@BeforeMethod
public void SetUp() throws IOException, ModelException {
bindings = new Properties();
File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir");
FileProjectManager.initialize(dir);
project = new Project();
ProjectMetadata pm = new ProjectMetadata();
pm.setName("TNG Test Project");
ProjectManager.singleton.registerProject(project, pm);
int index = project.columnModel.allocateNewCellIndex();
Column column = new Column(index,"Column A");
project.columnModel.addColumn(index, column, true);
options = mock(Properties.class);
bindings.put("project", project);
// Five rows of a's and five of 1s
for (int i = 0; i < 10; i++) {
Row row = new Row(1);
row.setCell(0, new Cell(i < 5 ? "a":new Integer(1), null));
project.rows.add(row);
}
}
@AfterMethod
public void TearDown() {
bindings = null;
}
/**
* Lookup a control function by name and invoke it with a variable number of args
*/
private static Object invoke(String name,Object... args) {
// registry uses static initializer, so no need to set it up
Function function = ControlFunctionRegistry.getFunction(name);
if (function == null) {
throw new IllegalArgumentException("Unknown function "+name);
}
if (args == null) {
return function.call(bindings,new Object[0]);
} else {
return function.call(bindings,args);
}
}
@Test
public void testInvalidParams() {
for (String op : new String[] {"and","or","xor"}) {
Assert.assertTrue(invoke(op) instanceof EvalError);
Assert.assertTrue(invoke(op, Boolean.TRUE, Boolean.TRUE, Boolean.TRUE) instanceof EvalError);
Assert.assertTrue(invoke(op, Boolean.TRUE, Integer.valueOf(1)) instanceof EvalError);
Assert.assertTrue(invoke(op, Integer.valueOf(1), Boolean.TRUE) instanceof EvalError);
Assert.assertTrue(invoke(op, Boolean.TRUE,"foo") instanceof EvalError);
Assert.assertTrue(invoke(op, "foo", Boolean.TRUE) instanceof EvalError);
Assert.assertTrue(invoke(op, Boolean.TRUE) instanceof EvalError);
}
String op = "not";
Assert.assertTrue(invoke(op) instanceof EvalError);
Assert.assertTrue(invoke(op, Boolean.TRUE,Boolean.TRUE) instanceof EvalError);
Assert.assertTrue(invoke(op, Integer.valueOf(1)) instanceof EvalError);
Assert.assertTrue(invoke(op, "foo") instanceof EvalError);
}
@Test
public void testBinary() {
for (String[] test : TRUTH_TABLE) {
String operator = test[0];
Boolean op1 = Boolean.valueOf(test[1]);
Boolean op2 = Boolean.valueOf(test[2]);
Boolean result = Boolean.valueOf(test[3]);
Assert.assertEquals(invoke(operator, op1, op2),result);
}
Assert.assertEquals(invoke("not", Boolean.TRUE),Boolean.FALSE);
Assert.assertEquals(invoke("not", Boolean.FALSE),Boolean.TRUE);
}
}

View File

@ -51,15 +51,15 @@ public class FingerprintTests extends RefineTest {
private static final String[][] testStrings = {
{"schön","schon"},
{"Ære Øre Åre", "aere are ore"},
{"Straße","strasse"},
// {"Ære Øre Åre", "are aere ore"},
// {"Straße","strasse"},
{"\tABC \t DEF ","abc def"}, // test leading and trailing whitespace
{"bbb\taaa","aaa bbb"},
{"müller","muller"},
// {"müller","mueller"}, // another possible interpretation
{"fiflij","fiflij"},
{"","אל"},
{"œ ӕ","ae oe"},
// {"fiflij","fiflij"},
// {"","אל"},
// {"œ ӕ","ae oe"},
{"",""},
};

View File

@ -111,10 +111,8 @@ public class ToFromConversionTests extends RefineTest {
@Test
public void testToString() {
// Assert.assertTrue(invoke("toString") instanceof EvalError);
Assert.assertNull(invoke("toString"));
// Assert.assertTrue(invoke("toString", (Object) null) instanceof EvalError);
Assert.assertNull(invoke("toString", (Object) null));
Assert.assertTrue(invoke("toString") instanceof EvalError);
Assert.assertTrue(invoke("toString", (Object) null) instanceof EvalError);
Assert.assertEquals(invoke("toString", Double.valueOf(100.0)),"100.0");
// Calendar
// Date

View File

@ -0,0 +1,178 @@
/*
Copyright 2010, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.google.refine.tests.model;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.refine.ProjectManager;
import com.google.refine.ProjectMetadata;
import com.google.refine.browsing.Engine;
import com.google.refine.browsing.RowVisitor;
import com.google.refine.expr.functions.FacetCount;
import com.google.refine.grel.Function;
import com.google.refine.io.FileProjectManager;
import com.google.refine.model.Cell;
import com.google.refine.model.Column;
import com.google.refine.model.ModelException;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
import com.google.refine.operations.EngineDependentOperation;
import com.google.refine.operations.row.RowRemovalOperation;
import com.google.refine.tests.RefineTest;
import com.google.refine.tests.util.TestUtils;
public class CacheTests extends RefineTest {
//{project=1718051861971, engine= ...}
//engine={ "facets" : ..., "mode":"row-based"}}
//facets = [{"type":"list","name":"row","columnName":"row","expression":"facetCount(value, 'value', 'row') > 1","omitBlank":false,"omitError":false,"selection":[],"selectBlank":false,"selectError":false,"invert":false}]
// {project=1718051861971, engine=
// Equivalent to duplicate facet on Column A with true selected
static final String ENGINE_JSON_DUPLICATES = "{\"facets\":[{\"type\":\"list\",\"name\":\"facet A\",\"columnName\":\"Column A\",\"expression\":\"facetCount(value, 'value', 'Column A') > 1\",\"omitBlank\":false,\"omitError\":false,\"selection\":[{\"v\":{\"v\":true,\"l\":\"true\"}}],\"selectBlank\":false,\"selectError\":false,\"invert\":false}],\"mode\":\"row-based\"}}";
@Override
@BeforeTest
public void init() {
logger = LoggerFactory.getLogger(this.getClass());
}
// dependencies
Project project;
Properties options;
JSONObject engine_config;
Engine engine;
Properties bindings;
@BeforeMethod
public void SetUp() throws JSONException, IOException, ModelException {
File dir = TestUtils.createTempDirectory("openrefine-test-workspace-dir");
FileProjectManager.initialize(dir);
project = new Project();
ProjectMetadata pm = new ProjectMetadata();
pm.setName("TNG Test Project");
ProjectManager.singleton.registerProject(project, pm);
int index = project.columnModel.allocateNewCellIndex();
Column column = new Column(index,"Column A");
project.columnModel.addColumn(index, column, true);
options = mock(Properties.class);
engine = new Engine(project);
engine_config = new JSONObject(ENGINE_JSON_DUPLICATES);
// engine_config.getJSONArray("facets").getJSONObject(0).getJSONArray("selection").put(new JSONArray());
engine.initializeFromJSON(engine_config);
engine.setMode(Engine.Mode.RowBased);
bindings = new Properties();
bindings.put("project", project);
}
@AfterMethod
public void TearDown() {
project = null;
options = null;
engine = null;
bindings = null;
}
/**
* Test for issue 567. Problem doesn't seem to occur when testing
* interactively, but this demonstrates that the facet count cache
* can get stale after row removal operations
*
* @throws Exception
*/
@Test
public void testIssue567() throws Exception {
for (int i = 0; i < 5; i++) {
Row row = new Row(5);
row.setCell(0, new Cell(i < 4 ? "a":"b", null));
project.rows.add(row);
}
engine.getAllRows().accept(project, new CountingRowVisitor(5)) ;
engine.getAllFilteredRows().accept(project, new CountingRowVisitor(4));
Function fc = new FacetCount();
Integer count = (Integer) fc.call(bindings, new Object[] {"a", "value", "Column A"});
Assert.assertEquals(count.intValue(), 4);
EngineDependentOperation op = new RowRemovalOperation(engine_config);
op.createProcess(project, options).performImmediate();
engine.getAllRows().accept(project, new CountingRowVisitor(1)) ;
engine.getAllFilteredRows().accept(project, new CountingRowVisitor(0));
count = (Integer) fc.call(bindings, new Object[] {"a", "value", "Column A"});
Assert.assertEquals(count.intValue(), 0);
}
class CountingRowVisitor implements RowVisitor {
private int count = 0;
private int target;
private CountingRowVisitor(int targetCount) {
target = targetCount;
}
@Override
public boolean visit(Project project, int rowIndex, Row row) {
count++;
return false;
}
@Override
public void start(Project project) {
count = 0;
}
@Override
public void end(Project project) {
Assert.assertEquals(count, target);
}
}
}

View File

@ -46,7 +46,6 @@ import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.refine.exporters.CsvExporter;
import com.google.refine.model.Cell;
import com.google.refine.model.Project;
import com.google.refine.model.Row;
@ -65,12 +64,8 @@ public class RowTests extends RefineTest {
Project project;
Properties options;
// System Under Test
CsvExporter SUT;
@BeforeMethod
public void SetUp() {
SUT = new CsvExporter();
writer = new StringWriter();
project = new Project();
options = mock(Properties.class);
@ -78,7 +73,6 @@ public class RowTests extends RefineTest {
@AfterMethod
public void TearDown() {
SUT = null;
writer = null;
project = null;
options = null;

View File

@ -0,0 +1,25 @@
package com.google.refine.tests.util;
import java.io.File;
import java.io.IOException;
public class TestUtils {
/**
* Create a temporary directory. NOTE: This is a quick and dirty
* implementation suitable for tests, not production code.
*
* @param name
* @return
* @throws IOException
*/
public static File createTempDirectory(String name)
throws IOException {
File dir = File.createTempFile(name, "");
dir.delete();
dir.mkdir();
return dir;
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -98,6 +98,9 @@ function registerCommands() {
RS.registerCommand(module, "transpose-rows-into-columns", new Packages.com.google.refine.commands.cell.TransposeRowsIntoColumnsCommand());
RS.registerCommand(module, "key-value-columnize", new Packages.com.google.refine.commands.cell.KeyValueColumnizeCommand());
RS.registerCommand(module, "load-language", Packages.com.google.refine.commands.lang.LoadLanguageCommand());
RS.registerCommand(module, "set-language", Packages.com.google.refine.commands.lang.SetLanguageCommand());
RS.registerCommand(module, "add-column", new Packages.com.google.refine.commands.column.AddColumnCommand());
RS.registerCommand(module, "add-column-by-fetching-urls", new Packages.com.google.refine.commands.column.AddColumnByFetchingURLsCommand());
RS.registerCommand(module, "remove-column", new Packages.com.google.refine.commands.column.RemoveColumnCommand());
@ -309,6 +312,7 @@ function init() {
"externals/jquery.eventstack-0.3.js",
"externals/jquery-ui/jquery-ui-1.8.20.custom.min.js",
"externals/date.js",
"externals/jquery.i18n.js",
"externals/CFInstall.min.js",
"scripts/chrome-frame.js",
@ -328,6 +332,7 @@ function init() {
"scripts/index/create-project-ui.js",
"scripts/index/open-project-ui.js",
"scripts/index/import-project-ui.js",
"scripts/index/lang-settings-ui.js",
"scripts/index/default-importing-controller/controller.js",
"scripts/index/default-importing-controller/file-selection-panel.js",
@ -380,10 +385,11 @@ function init() {
"externals/jquery-1.7.2.min.js",
"externals/jquery.cookie.js",
"externals/jquery.eventstack-0.3.js",
"externals/suggest/suggest-4_1.min.js",
"externals/suggest/suggest-4_2.min.js",
"externals/jquery-ui/jquery-ui-1.8.20.custom.min.js",
"externals/imgareaselect/jquery.imgareaselect.js",
"externals/date.js",
"externals/jquery.i18n.js",
"externals/CFInstall.min.js",
"scripts/chrome-frame.js",
@ -445,7 +451,7 @@ function init() {
"project/styles",
module,
[
"externals/suggest/css/suggest-4_1.min.css",
"externals/suggest/css/suggest-4_2.min.css",
"externals/jquery-ui/css/ui-lightness/jquery-ui-1.8.20.custom.css",
"externals/imgareaselect/css/imgareaselect-default.css",
@ -485,18 +491,19 @@ function init() {
[
"externals/jquery-1.7.2.min.js",
"externals/jquery.cookie.js",
"externals/suggest/suggest-4_1.min.js",
"externals/suggest/suggest-4_2.min.js",
"externals/jquery-ui/jquery-ui-1.8.20.custom.min.js",
"externals/imgareaselect/jquery.imgareaselect.js",
"externals/date.js",
"scripts/preferences.js"
"scripts/preferences.js",
"externals/jquery.i18n.js",
]
);
ClientSideResourceManager.addPaths(
"preferences/styles",
module,
[
"externals/suggest/css/suggest-4_1.min.css",
"externals/suggest/css/suggest-4_2.min.css",
"externals/jquery-ui/css/ui-lightness/jquery-ui-1.8.20.custom.css",
"styles/jquery-ui-overrides.less",
"styles/common.less",

View File

@ -0,0 +1,2 @@
(function(f){f.i18n={dict:null,plural:null,setDictionary:function(a){null===this.dict?this.dict=a:f.extend(this.dict,a)},setPlural:function(a){this.plural=a},_p:function(a,d,e){var c=this.dict[a],b=[];b.push(e);if(void 0===c||null===this.plural)return this.printf(1<e?d:a,b);a=this.plural.replace(/n%/g,e+"%");eval(a);return this.printf(c[plural],b)},_:function(a,d){var e=a;this.dict&&this.dict[a]&&(e=this.dict[a]);return this.printf(e,d)},printf:function(a,d){if(!d)return a;for(var e="",c=/%(\d+)\$s/g,
b=c.exec(a);b;){var f=parseInt(b[1],10)-1;a=a.replace("%"+b[1]+"$s",d[f]);b=c.exec(a)}c=a.split("%s");if(1<c.length)for(b=0;b<d.length;b++)0<c[b].length&&c[b].lastIndexOf("%")==c[b].length-1&&(c[b]+="s"+c.splice(b+1,1)[0]),e+=c[b]+d[b];return e+c[c.length-1]}};f.fn._t=function(a,d){return f(this).text(f.i18n._(a,d))}})(jQuery);

Some files were not shown because too many files have changed in this diff Show More