http://www.mediawiki.org/wiki/Special:Code/MediaWiki/68396
Revision: 68396 Author: daniel Date: 2010-06-22 09:41:37 +0000 (Tue, 22 Jun 2010) Log Message: ----------- prepare for merging more info into global thesaurus: concept types, properties, definitions Modified Paths: -------------- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/ConceptType.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/Corpus.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/DatasetIdentifier.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/StoreBackedApp.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/ManagementConsole.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/GlobalConceptStoreSchema.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/LocalConceptStoreSchema.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/PropertyStoreSchema.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/WikiWordConceptStoreSchema.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseGlobalConceptStore.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseLocalConceptStore.java trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseWikiWordConceptStore.java trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabasePropertyStoreBuilder.java Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/ConceptType.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/ConceptType.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/ConceptType.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -165,7 +165,7 @@ * (i.e. wiki project). The ConceptTypeSet MUST support the canonical ConceptTypes, and * MAY support additional ConceptTypes defined for that corpus. */ - protected static ConceptTypeSet getConceptTypes(Corpus corpus, String... configPackages) { + protected static ConceptTypeSet getConceptTypes(DatasetIdentifier dataset, String... configPackages) { ConceptTypeSet ct = new ConceptTypeSet(); //TODO: merge files for language and specific wiki! @@ -173,12 +173,12 @@ ClassLoader loader = ConceptType.class.getClassLoader(); if (canonicalConceptTypes!=null) ct.addAll(canonicalConceptTypes); - loadConceptTypes(loader, "de.brightbyte.wikiword", corpus, ct); - loadConceptTypes(loader, "de.brightbyte.wikiword.wikis", corpus, ct); + loadConceptTypes(loader, "de.brightbyte.wikiword", dataset, ct); + loadConceptTypes(loader, "de.brightbyte.wikiword.wikis", dataset, ct); if (configPackages!=null) { for (String pkg: configPackages) { - loadConceptTypes(loader, pkg, corpus, ct); + loadConceptTypes(loader, pkg, dataset, ct); } } @@ -191,21 +191,21 @@ return into; } - protected static void loadConceptTypes(ClassLoader loader, String prefix, Corpus corpus, ConceptTypeSet into) { + protected static void loadConceptTypes(ClassLoader loader, String prefix, DatasetIdentifier dataset, ConceptTypeSet into) { if (loader==null) loader= ClassLoader.getSystemClassLoader(); String p = prefix.replace('.', '/'); URL u = loader.getResource(p + "/ConceptTypes.properties"); if (u!=null) loadConceptTypes(u, into); - if ( corpus != null) { - u = loader.getResource(p + "/ConceptTypes_" + corpus.getFamily() + ".properties"); + if ( dataset != null && dataset instanceof Corpus) { //XXX: per-language types are a BAD IDEA! + u = loader.getResource(p + "/ConceptTypes_" + ((Corpus)dataset).getFamily() + ".properties"); if (u!=null) loadConceptTypes(u, into); - u = loader.getResource(p + "/ConceptTypes_" + corpus.getLanguage() + ".properties"); + u = loader.getResource(p + "/ConceptTypes_" + ((Corpus)dataset).getLanguage() + ".properties"); if (u!=null) loadConceptTypes(u, into); - u = loader.getResource(p + "/ConceptTypes_" + corpus.getClassSuffix() + ".properties"); + u = loader.getResource(p + "/ConceptTypes_" + ((Corpus)dataset).getClassSuffix() + ".properties"); if (u!=null) loadConceptTypes(u, into); } } Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/Corpus.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/Corpus.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/Corpus.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -28,12 +28,8 @@ protected NamespaceSet namespaces; protected Map<String, Interwiki> interwikiMap; - protected ConceptTypeSet conceptTypes; - - protected String[] configPackages; - public Corpus(String collection, String name, String dbPrefix, String domain, String classSuffix, String language, String family, String[] configPackages) { - super(collection, name, dbPrefix); + super(collection, name, dbPrefix, configPackages); this.domain = domain; this.dbPrefix = dbPrefix; this.classSuffix = classSuffix; @@ -41,11 +37,8 @@ this.family = family; this.wikiName = language + "wiki"; - this.configPackages = configPackages==null ? new String[] {} : configPackages; - url = WikiWordIdentifiers.corpusURL(domain); - - this.conceptTypes = ConceptType.getConceptTypes(this, configPackages); + this.namespaces = Namespace.getNamespaces(this); this.interwikiMap = Interwiki.getInterwikiMap(this); } @@ -221,10 +214,6 @@ return interwikiMap; } - public ConceptTypeSet getConceptTypes() { - return conceptTypes; - } - @Override public String toString() { return getDomain(); Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/DatasetIdentifier.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/DatasetIdentifier.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/DatasetIdentifier.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -1,17 +1,26 @@ package de.brightbyte.wikiword; +import java.util.Collections; +import java.util.List; + public class DatasetIdentifier { protected String collection; protected String name; protected String dbPrefix; - public DatasetIdentifier(String collection, String name, String dbPrefix) { + protected String[] configPackages; + protected ConceptTypeSet conceptTypes; + + public DatasetIdentifier(String collection, String name, String dbPrefix, String[] configPackages) { super(); this.collection = collection; this.name = name; this.dbPrefix = dbPrefix; + + this.configPackages = configPackages==null ? new String[] {} : configPackages; + this.conceptTypes = ConceptType.getConceptTypes(this, configPackages); } public String getName() { @@ -73,11 +82,23 @@ return db; } - public static DatasetIdentifier forName(String collection, String name) { - return new DatasetIdentifier(collection, name, dbPrefix(collection, name)); + public static DatasetIdentifier forName(String collection, String name, TweakSet tweaks) { + String[] configPackages = getConfigPackages(tweaks); + + return new DatasetIdentifier(collection, name, dbPrefix(collection, name), configPackages); } + protected static String[] getConfigPackages(TweakSet tweaks) { + List<String> pkg = tweaks.getTweak("wikiword.ConfigPackages", Collections.<String>emptyList()); + return pkg.toArray(new String[pkg.size()]); + } + public String getCollection() { return collection; } + + public ConceptTypeSet getConceptTypes() { + return conceptTypes; + } + } Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/StoreBackedApp.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/StoreBackedApp.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/StoreBackedApp.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -84,7 +84,7 @@ dataset = Corpus.forName(c, n, tweaks); } else { - dataset = DatasetIdentifier.forName(c, n); + dataset = DatasetIdentifier.forName(c, n, tweaks); } return dataset; Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/ManagementConsole.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/ManagementConsole.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/query/ManagementConsole.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -55,9 +55,11 @@ List<String> params = args.getParameters(); DatabaseConnectionInfo dbinfo = new DatabaseConnectionInfo(dbfile); - DatasetIdentifier dataset = DatasetIdentifier.forName("dummy", "thingy"); - TweakSet tweaks = new TweakSet(); + TweakSet tweaks = new TweakSet(); //TODO: load?... + + DatasetIdentifier dataset = DatasetIdentifier.forName("dummy", "thingy", tweaks); + WikiWordStoreSchema db = new WikiWordStoreSchema(dataset, dbinfo, tweaks, false); db.open(); @@ -200,7 +202,7 @@ public DatabaseWikiWordConceptStore getConceptStore(String name) throws SQLException, PersistenceException { TweakSet tweaks = new TweakSet(); - DatasetIdentifier dataset = DatasetIdentifier.forName("", name); + DatasetIdentifier dataset = DatasetIdentifier.forName("", name, tweaks); DataSource ds = new SingletonDataSource(db.getConnection()); DatabaseWikiWordConceptStore store = DatabaseConceptStores.createConceptStore(ds, dataset, tweaks, true, true); Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/GlobalConceptStoreSchema.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/GlobalConceptStoreSchema.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/GlobalConceptStoreSchema.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -66,6 +66,9 @@ groupStats.add( new GroupStatsSpec("concept", "language_count", null)); relationTable.addField( new DatabaseField(this, "langref", "INT", "DEFAULT 0", true, KeyType.INDEX ) ); + + definitionTable.addField( new DatabaseField(this, "lang", getTextType(10), null, true, null ) ); + definitionTable.addKey( new DatabaseKey(this, KeyType.PRIMARY, "concept_lang", new String[] {"concept", "lang"}) ); //meaningTable.addField( new DatabaseField(this, "lang", getTextType(10), null, true, null) ); //NOTE: replace key defined by WikiWordConceptStoreSchema! @@ -230,7 +233,7 @@ int i = 0; for (String l: ll) { - cc[i++] = DatasetIdentifier.forName(getCollectionName(), l); + cc[i++] = DatasetIdentifier.forName(getCollectionName(), l, tweaks); } return cc; Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/LocalConceptStoreSchema.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/LocalConceptStoreSchema.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/LocalConceptStoreSchema.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -18,7 +18,6 @@ public class LocalConceptStoreSchema extends WikiWordConceptStoreSchema { protected EntityTable resourceTable; - protected EntityTable definitionTable; protected EntityTable sectionTable; protected RelationTable meaningTable; @@ -60,7 +59,9 @@ linkTable.addField( new DatabaseField(this, "term_text", getTextType(255), null, true, null) ); linkTable.addField( new DatabaseField(this, "rule", "INT", null, true, KeyType.INDEX) ); linkTable.addKey( new DatabaseKey(this, KeyType.INDEX, "term_target", new String[] {"term_text", "target"}) ); - + + definitionTable.addField( new ReferenceField(this, "resource", "INT", null, true, KeyType.UNIQUE, "resource", "id", null ) ); + definitionTable.addKey( new DatabaseKey(this, KeyType.PRIMARY, "concept", new String[] {"concept"}) ); //-------- resourceTable = new EntityTable(this, "resource", getDefaultTableAttributes()); @@ -74,13 +75,6 @@ resourceTable.setAutomaticField("id"); addTable(resourceTable); - - definitionTable = new EntityTable(this, "definition", getDefaultTableAttributes()); - definitionTable.addField( new ReferenceField(this, "concept", "INT", null, true, KeyType.PRIMARY, "concept", "id", null ) ); - definitionTable.addField( new ReferenceField(this, "resource", "INT", null, true, KeyType.UNIQUE, "resource", "id", null ) ); - definitionTable.addField( new DatabaseField(this, "definition", getTextType(1024*8), null, true, null ) ); - definitionTable.setAutomaticField(null); - addTable(definitionTable); sectionTable = new EntityTable(this, "section", getDefaultTableAttributes()); sectionTable.addField( new ReferenceField(this, "resource", "INT", null, true, KeyType.INDEX, "resource", "id", null ) ); Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/PropertyStoreSchema.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/PropertyStoreSchema.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/PropertyStoreSchema.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -20,23 +20,23 @@ protected RelationTable propertyTable; protected DatasetIdentifier dataset; - public PropertyStoreSchema(DatasetIdentifier dataset, Connection connection, TweakSet tweaks, boolean useFlushQueue) throws SQLException { + public PropertyStoreSchema(DatasetIdentifier dataset, Connection connection, boolean global, TweakSet tweaks, boolean useFlushQueue) throws SQLException { super(dataset, connection, tweaks, useFlushQueue ); - init(dataset, tweaks); + init(dataset, global, tweaks); } - public PropertyStoreSchema(DatasetIdentifier dataset, DataSource connectionInfo, TweakSet tweaks, boolean useFlushQueue) throws SQLException { + public PropertyStoreSchema(DatasetIdentifier dataset, DataSource connectionInfo, boolean global, TweakSet tweaks, boolean useFlushQueue) throws SQLException { super(dataset, connectionInfo, tweaks, useFlushQueue); - init(dataset, tweaks); + init(dataset, global, tweaks); } - private void init(DatasetIdentifier dataset, TweakSet tweaks) { + private void init(DatasetIdentifier dataset, boolean global, TweakSet tweaks) { this.dataset = dataset; propertyTable = new RelationTable(this, "property", getDefaultTableAttributes()); - propertyTable.addField( new ReferenceField(this, "resource", "INT", null, false, KeyType.INDEX, "resource", "id", null ) ); + if (!global) propertyTable.addField( new ReferenceField(this, "resource", "INT", null, false, KeyType.INDEX, "resource", "id", null ) ); propertyTable.addField( new ReferenceField(this, "concept", "INT", null, false, KeyType.INDEX, "concept", "id", null ) ); - propertyTable.addField( new ReferenceField(this, "concept_name", getTextType(255), null, true, KeyType.INDEX, "concept", "name", null ) ); + if (!global) propertyTable.addField( new ReferenceField(this, "concept_name", getTextType(255), null, true, KeyType.INDEX, "concept", "name", null ) ); propertyTable.addField( new DatabaseField(this, "property", getTextType(255), null, true, KeyType.INDEX) ); propertyTable.addField( new DatabaseField(this, "value", getTextType(255), null, true, null) ); propertyTable.addKey( new DatabaseKey(this, KeyType.INDEX, "concept_property", new String[] {"concept_name", "property"}) ); Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/WikiWordConceptStoreSchema.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/WikiWordConceptStoreSchema.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/schema/WikiWordConceptStoreSchema.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -23,6 +23,8 @@ protected RelationTable relationTable; protected RelationTable langlinkTable; + protected EntityTable definitionTable; + public WikiWordConceptStoreSchema(DatasetIdentifier dataset, Connection connection, TweakSet tweaks, boolean useFlushQueue) throws SQLException { super(dataset, connection, tweaks, useFlushQueue ); init(tweaks); @@ -76,6 +78,12 @@ relationTable.addField( new DatabaseField(this, "bilink", "INT", "DEFAULT 0", true, KeyType.INDEX ) ); relationTable.addKey( new DatabaseKey(this, KeyType.PRIMARY, "one_two", new String[] {"concept1", "concept2"}) ); addTable(relationTable); + + definitionTable = new EntityTable(this, "definition", getDefaultTableAttributes()); + definitionTable.addField( new ReferenceField(this, "concept", "INT", null, true, null, "concept", "id", null ) ); + definitionTable.addField( new DatabaseField(this, "definition", getTextType(1024*8), null, true, null ) ); + definitionTable.setAutomaticField(null); + addTable(definitionTable); } @Override Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseGlobalConceptStore.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseGlobalConceptStore.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseGlobalConceptStore.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -27,6 +27,7 @@ import de.brightbyte.wikiword.model.LocalConcept; import de.brightbyte.wikiword.schema.ConceptInfoStoreSchema; import de.brightbyte.wikiword.schema.GlobalConceptStoreSchema; +import de.brightbyte.wikiword.schema.PropertyStoreSchema; import de.brightbyte.wikiword.schema.StatisticsStoreSchema; /** @@ -299,8 +300,11 @@ } ///////////////////////////////////////////////////////////////////////////////////////////// + @Override protected PropertyStore<GlobalConcept> newPropertyStore() throws SQLException, PersistenceException { - throw new UnsupportedOperationException("property stores are not yet supported for a global thesaurus."); + PropertyStoreSchema schema = new PropertyStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), true, tweaks, false); + + return new DatabasePropertyStore<GlobalConcept>(this, schema, tweaks); } protected class DatabaseGlobalConceptInfoStore extends DatabaseConceptInfoStore<GlobalConcept> { Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseLocalConceptStore.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseLocalConceptStore.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseLocalConceptStore.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -34,6 +34,7 @@ import de.brightbyte.wikiword.schema.ConceptInfoStoreSchema; import de.brightbyte.wikiword.schema.LocalConceptStoreSchema; import de.brightbyte.wikiword.schema.LocalStatisticsStoreSchema; +import de.brightbyte.wikiword.schema.PropertyStoreSchema; import de.brightbyte.wikiword.schema.StatisticsStoreSchema; /** @@ -426,4 +427,13 @@ StatisticsStoreSchema schema = new LocalStatisticsStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), tweaks, false); return new DatabaseLocalStatisticsStore(schema, tweaks); } + + @Override + protected PropertyStore<LocalConcept> newPropertyStore() throws SQLException, PersistenceException { + PropertyStoreSchema schema = new PropertyStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), false, tweaks, false); + + return new DatabasePropertyStore<LocalConcept>(this, schema, tweaks); + } + + } Modified: trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseWikiWordConceptStore.java =================================================================== --- trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseWikiWordConceptStore.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWord/src/main/java/de/brightbyte/wikiword/store/DatabaseWikiWordConceptStore.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -279,12 +279,6 @@ return new CalculatedProximityStore<T>(store, getConceptFactory()); } - protected PropertyStore<T> newPropertyStore() throws SQLException, PersistenceException { - PropertyStoreSchema schema = new PropertyStoreSchema(getDatasetIdentifier(), getDatabaseAccess().getConnection(), tweaks, false); - - return new DatabasePropertyStore<T>(this, schema, tweaks); - } - private DatabaseStatisticsStore statsStore; private DatabaseConceptInfoStore<T> infoStore; @@ -333,6 +327,8 @@ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + protected abstract PropertyStore<T> newPropertyStore() throws SQLException, PersistenceException; + public abstract class DatabaseStatisticsStore extends DatabaseWikiWordStore implements StatisticsStore<T> { protected EntityTable statsTable; Modified: trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabasePropertyStoreBuilder.java =================================================================== --- trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabasePropertyStoreBuilder.java 2010-06-22 09:08:20 UTC (rev 68395) +++ trunk/WikiWord/WikiWordBuilder/src/main/java/de/brightbyte/wikiword/store/builder/DatabasePropertyStoreBuilder.java 2010-06-22 09:41:37 UTC (rev 68396) @@ -24,7 +24,7 @@ public DatabasePropertyStoreBuilder(Corpus corpus, Connection connection, TweakSet tweaks) throws SQLException, PersistenceException { this(new LocalConceptStoreSchema(corpus, connection, tweaks, true), - new PropertyStoreSchema(corpus, connection, tweaks, true), + new PropertyStoreSchema(corpus, connection, false, tweaks, true), null, tweaks, null); } @@ -39,7 +39,7 @@ this((LocalConceptStoreSchema)conceptStore.getDatabaseAccess(), new PropertyStoreSchema(conceptStore.getCorpus(), conceptStore.getDatabaseAccess().getConnection(), - tweaks, true), + false, tweaks, true), conceptStore.idManager, tweaks, conceptStore.getAgenda()); _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs