/* TRelation.java - SQL operations with the table 'relation' in SQLite Android
* Wiktionary parsed database.
*
* Copyright (c) 2009-2012 Andrew Krizhanovsky <andrew.krizhanovsky at gmail.com>
* Distributed under EPL/LGPL/GPL/AL/BSD multi-license.
*/
package wikokit.base.wikt.sql;
import wikokit.base.wikt.constant.Relation;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/** An operations with the table 'relation' in MySQL wiktionary_parsed database.
*
* @see wikt.word.WRelation
*/
public class TRelation {
private static final boolean DEBUG = true;
/** Unique identifier in the table 'relation'. */
private int id;
/** One sense of a word. */
private TMeaning meaning; // int meaning_id;
/** Text (wikified sometimes). */
private TWikiText wiki_text; // int wiki_text_id
/** Semantic relation. */
private TRelationType relation_type; // int relation_type_id
/** Summary of the definition for which synonyms (antonyms, etc.) are being given,
* e.g. "flrink with cumplus" or "furp" in text
* <PRE>
* * (''flrink with cumplus''): [[flrink]], [[pigglehick]]
* * (''furp''): [[furp]], [[whoodleplunk]]
* </PRE>
*
* Disadvantage: the summary "flrink with cumplus" is repeated twice
* in table for "flrink" and "pigglehick".
*
* Comment: is used in English Wiktionary, see http://en.wiktionary.org/wiki/Wiktionary:Entry_layout_explained#Synonyms
* It is not used in Russian Wiktionary (NULL in database).
*/
private String meaning_summary;
private final static TRelation[] NULL_TRELATION_ARRAY = new TRelation[0];
public TRelation(int _id,TMeaning _meaning,TWikiText _wiki_text,
TRelationType _relation_type,String _meaning_summary)
{
id = _id;
meaning = _meaning;
wiki_text = _wiki_text;
relation_type = _relation_type;
meaning_summary = _meaning_summary;
}
/** Gets unique ID from database */
public int getID() {
return id;
}
/** Gets meaning from database */
public TMeaning getMeaning() {
return meaning;
}
/** Gets a summary of the semantic relation meaning (e.g. title of list of synonyms). */
public String getMeaningSummary() {
return meaning_summary;
}
/** Gets text (wikified sometimes). */
public TWikiText getWikiText() {
return wiki_text;
}
/** Gets type of semantic relation. */
public Relation getRelationType() {
if(null == relation_type)
return null;
return relation_type.getRelation();
}
/** Inserts records into tables: 'wiki_text' and 'relation'.
* The insertion into 'wiki_text' results in updating records in tables:
* 'wiki_text_words', 'page_inflecton', 'inflection', and 'page'.
*
* @param tmeaning corresponding record in table 'meaning' to this relation
* @param meaning_n number of this meaning (for polysemous words)
* (e.g. m_relations.get(Relation.hypernymy)[meaning_n] = WRelation for this meaning.)
* @param m_relations map from semantic relation (e.g. synonymy) to array of WRelation (one WRelation contains a list of synonyms for one meaning).
*/
/*public static void storeToDB (Connect connect,TMeaning tmeaning,int meaning_n,
Map<Relation, WRelation[]> m_relations) {
if(null == tmeaning || null == m_relations || m_relations.isEmpty()) return;
Collection<Relation> rr = m_relations.keySet();
for(Relation r : rr) {
TRelationType trelation_type = TRelationType.getRelationFast(r);
WRelation[] wr = m_relations.get(r);
if(meaning_n < wr.length && null != wr[meaning_n]) {
WRelation cur_rel = wr[meaning_n];
String meaning_summary = cur_rel.getMeaningSummary();
WikiText[] phrases = cur_rel.get();
for(WikiText p : phrases) {
TWikiText twiki_text = TWikiText.storeToDB(connect, p);
if(null != twiki_text) {
TRelation.insert(connect, tmeaning, twiki_text,
trelation_type, meaning_summary);
}
}
}
}
}*/
/** Inserts record into the table 'relation'.<br><br>
* INSERT INTO relation (meaning_id,wiki_text_id,relation_type_id) VALUES (11,12,13);
* or
* INSERT INTO relation (meaning_id,wiki_text_id,relation_type_id,meaning_summary) VALUES (11,12,13,"sum");
*
* @param meaning corresponding meaning of the word
* @param wiki_text synonym word (or phrase), or antonym, etc.
* @param relation_type semantic relation
* @param meaning_summary summary of the definition for which synonyms
* (antonyms, etc.) are being given. It could be null.
*
* @return null if data is absent
*/
/*public static TRelation insert (Connect connect,
TMeaning meaning,TWikiText wiki_text,TRelationType relation_type,
String meaning_summary) {
if(null == meaning || null == wiki_text || null == relation_type) {
System.err.println("Error (wikt_parsed TRelation.insert()):: null arguments, meaning="+meaning+", wiki_text="+wiki_text+", relation_type="+relation_type);
return null;
}
StringBuilder str_sql = new StringBuilder();
TRelation relation = null;
try
{
boolean b_sum = null != meaning_summary && meaning_summary.length() > 0;
Statement s = connect.conn.createStatement ();
try {
str_sql.append("INSERT INTO relation (meaning_id,wiki_text_id,relation_type_id");
if(b_sum)
str_sql.append(",meaning_summary");
str_sql.append(") VALUES (");
str_sql.append(meaning.getID());
str_sql.append(",");
str_sql.append(wiki_text.getID());
str_sql.append(",");
str_sql.append(relation_type.getID());
if(b_sum) {
str_sql.append(",\"");
str_sql.append(PageTableBase.convertToSafeStringEncodeToDBWunderscore(connect, meaning_summary));
str_sql.append("\"");
}
str_sql.append(")");
s.executeUpdate (str_sql.toString());
} finally {
s.close();
}
s = connect.conn.createStatement ();
try {
ResultSet rs = s.executeQuery ("SELECT LAST_INSERT_ID() as id");
try {
if (rs.next ())
relation = new TRelation(rs.getInt("id"), meaning, wiki_text,
relation_type, meaning_summary);
} finally {
rs.close();
}
} finally {
s.close();
}
}catch(SQLException ex) {
System.err.println("SQLException (TRelation.insert()):: sql='" + str_sql.toString() + "' " + ex.getMessage());
}
return relation;
}*/
/** Selects rows from the table 'relation' by the meaning_id.<br><br>.
* SELECT id,wiki_text_id,relation_type_id,meaning_summary FROM relation WHERE meaning_id=11;
* @return empty array if data is absent
*/
public static TRelation[] get (SQLiteDatabase db,TMeaning _meaning) {
if(null == _meaning) {
System.err.println("Error (TRelation.get()):: null argument: meaning.");
return NULL_TRELATION_ARRAY;
}
List<TRelation> list_rel = null;
// SELECT id,wiki_text_id,relation_type_id,meaning_summary FROM relation WHERE meaning_id=1
Cursor c = db.query("relation",
new String[] { "id", "wiki_text_id", "relation_type_id", "meaning_summary"},
"meaning_id=" + _meaning.getID(),
null, null, null, null);
if (c.moveToFirst()) {
do {
int i_id = c.getColumnIndexOrThrow("id");
int i_wiki_text_id = c.getColumnIndexOrThrow("wiki_text_id");
int i_relation_type_id = c.getColumnIndexOrThrow("relation_type_id");
int i_meaning_summary = c.getColumnIndexOrThrow("meaning_summary");
int _id = c.getInt(i_id);
int wiki_text_id = c.getInt(i_wiki_text_id);
TWikiText wt = wiki_text_id < 1 ? null : TWikiText.getByID(db, wiki_text_id);
int rtid = c.getInt(i_relation_type_id);
TRelationType r = TRelationType.getRelationFast(rtid);
if(null != wt && null != r) {
if(null == list_rel)
list_rel = new ArrayList<TRelation>();
String sum = c.getString(i_meaning_summary);
list_rel.add(new TRelation(_id, _meaning, wt, r, sum));
}
} while (c.moveToNext());
}
if (c != null && !c.isClosed()) {
c.close();
}
if(null == list_rel)
return NULL_TRELATION_ARRAY;
return (TRelation[])list_rel.toArray(NULL_TRELATION_ARRAY);
}
/** Counts number of rows from the table 'relation' related to the meaning_id.<br><br>.
* SELECT COUNT(*) as a FROM relation WHERE meaning_id=11;
* @return empty array if data is absent
*/
public static int count (SQLiteDatabase db,TMeaning _meaning) {
if(null == _meaning) {
System.err.println("Error (wikt_parsed TRelation.count()):: null argument: meaning.");
return 0;
}
int n = 0;
final String sql = "SELECT COUNT(*) FROM relation WHERE meaning_id=?";
Cursor c = db.rawQuery(sql, new String[] { "" + _meaning.getID() });
if (c.moveToFirst())
n = c.getInt(0);
if (c != null && !c.isClosed()) {
c.close();
}
return n;
}
/** Selects row from the table 'relation' by ID.<br><br>
* SELECT meaning_id,wiki_text_id,relation_type_id,meaning_summary FROM relation WHERE id=1;
* @return null if data is absent
*/
public static TRelation getByID (SQLiteDatabase db,int _id) {
if(_id < 0) {
System.err.println("Error (TRelation.getByID()):: ID is negative.");
return null;
}
// SELECT meaning_id,wiki_text_id,relation_type_id,meaning_summary FROM relation WHERE id=1
Cursor c = db.query("relation",
new String[] { "meaning_id", "wiki_text_id", "relation_type_id", "meaning_summary"},
"id=" + _id,
null, null, null, null);
TRelation relation = null;
if (c.moveToFirst()) {
int i_meaning_id = c.getColumnIndexOrThrow("meaning_id");
int i_wiki_text_id = c.getColumnIndexOrThrow("wiki_text_id");
int i_relation_type_id = c.getColumnIndexOrThrow("relation_type_id");
int i_meaning_summary = c.getColumnIndexOrThrow("meaning_summary");
TMeaning m = TMeaning. getByID( db, c.getInt(i_meaning_id));
TWikiText wt = TWikiText.getByID( db, c.getInt(i_wiki_text_id));
TRelationType r = TRelationType.getRelationFast(
c.getInt(i_relation_type_id));
if(null != m && null != wt && null != r) {
String sum = c.getString(i_meaning_summary); // could be null
relation = new TRelation(_id, m, wt, r, sum);
}
}
if (c != null && !c.isClosed()) {
c.close();
}
return relation;
}
/** Deletes a row from the table 'relation' by ID.<br><br>
* DELETE FROM relation WHERE id=1;
* @param id unique ID in the table `relation`
*/
/*public static void delete (Connect connect,TRelation relation) {
if(null == relation) {
System.err.println("Error (wikt_parsed TRelation.delete()):: null argument page.");
return;
}
StringBuilder str_sql = new StringBuilder();
try {
Statement s = connect.conn.createStatement ();
try {
str_sql.append("DELETE FROM relation WHERE id=");
str_sql.append(relation.getID());
s.execute (str_sql.toString());
} finally {
s.close();
}
} catch(SQLException ex) {
System.err.println("SQLException (wikt_parsed TRelation.java delete()):: sql='" + str_sql.toString() + "' " + ex.getMessage());
}
}*/
/** Gets all semantic relation (pairs of word).
* @return pairs of words,
* e.g. car -> carriage, car -> automobile (synonyms)
* car -> vehicle (hyperohym)
* or empty map, if relations are absent
*/
public static Map<String, List<String>> getAllWordPairs (SQLiteDatabase db) {
assert(false);
// for each relation: get page<->wiki_text<->wiki_word + todo: type of relation
long t_start;
float t_work;
/*
int n_total = Statistics.Count(SQLiteDatabase db, "relation");
System.out.println("Total relations: " + n_total);
if(-1 == n_total)
return null;
t_start = System.currentTimeMillis();
StringBuilder str_sql = new StringBuilder();
Map<String,List<String>> m_words = null;
try {
Statement s = connect.conn.createStatement ();
try {
str_sql.append("SELECT meaning_id,wiki_text_id FROM relation");
//str_sql.append("SELECT meaning_id,wiki_text_id FROM relation LIMIT 1000");
ResultSet rs = s.executeQuery (str_sql.toString());
try {
m_words = new HashMap<String,List<String>> ();
int n_cur = 0;
while (rs.next ())
{
//int id = rs.getInt("id");
TMeaning m = TMeaning. getByID( connect, rs.getInt("meaning_id"));
TWikiText wt = TWikiText.getByID( connect, rs.getInt("wiki_text_id"));
//int wiki_text_id = rs.getInt("wiki_text_id");
// skip today
//TRelationType r = TRelationType.getRelationFast(rs.getInt("relation_type_id"));
//TRelation relation = null;
//if(null != m && null != wt) && null != r)
// relation = new TRelation(id, m, wt, r);
String page = null;
if(null != m) {
TLangPOS lang_pos = m.getLangPOS(connect);
if(null != lang_pos) {
TPage tpage = lang_pos.getPage();
if(null != tpage) {
page = tpage.getPageTitle();
}
}
}
String w_rel = null; // wiki word relation
if(null != page) {
//TWikiTextWords t_word = TWikiTextWords.getByID(connect, id);
TWikiTextWords t_word = TWikiTextWords.getOneByWikiText(connect, wt);
if(null != t_word) {
TPage tpage = t_word.getPage();
if(null != tpage) {
w_rel = tpage.getPageTitle();
}
}
}
if(null != page && null != w_rel) {
List<String> list_rel = m_words.get(page);
if(null == list_rel) {
list_rel = new ArrayList<String>();
list_rel.add(w_rel);
m_words.put(page, list_rel);
} else {
if(!list_rel.contains(w_rel))
list_rel.add(w_rel);
}
}
if(DEBUG && 0 == ++n_cur % 1000) { // % 100
//if(n_cur<10900) continue;
long t_cur, t_remain;
t_cur = System.currentTimeMillis() - t_start;
t_remain = (long)((n_total - n_cur) * t_cur/(60f*1000f*(float)(n_cur)));
// where time for 1 page = t_cur / n_cur
// in min, since /(60*1000)
t_cur = (long)(t_cur/(60f*1000f));
//t_cur = t_cur/(60f*1000f));
System.out.println(n_cur + ": [" + page + ", " + w_rel +
"], duration: " + t_cur + // t_cur/(60f*1000f) +
" min, remain: " + t_remain +
" min");
}
}
} finally {
rs.close();
}
} finally {
s.close();
}
} catch(SQLException ex) {
System.err.println("SQLException (wikt_parsed TRelation.java getAllWordPairs()):: sql='" + str_sql.toString() + "' " + ex.getMessage());
}
long t_end;
t_end = System.currentTimeMillis();
t_work = (t_end - t_start)/1000f; // in sec
System.out.println("\n\nTime sec:" + t_work +
"\nTotal relations: " + n_total);
return m_words;*/
return null;
}
/** Gets a word defined by a semantic relation (e.g. the page "car" contains "[[automobile]]"
* in a section "Synonyms", then the "automobile" will be returned).
* @param trelation defines relation (e.g. synonymy) and source word (e.g. "car")
* @return word defined by a semantic relation (e.g. "automobile" for "car"), or null if search failed
*/
public static TPage getWikifiedPage (SQLiteDatabase db,TRelation trelation) {
if(null == trelation)
return null;
TWikiText twt = trelation.getWikiText();
if(null == twt)
return null;
TWikiTextWords t_word = TWikiTextWords.getOneByWikiText(db, twt);
if(null != t_word)
return t_word.getPage();
return null;
}
/** Gets type of semantic relation between a pair of word: title of a page
* (page_title) and word on this page (word).
*/
private static Relation getRelationBetweenPageTitleAndWord (SQLiteDatabase db,String page_title,String word) {
if(0 == word.length() || 0 == page_title.length() || word.equals(page_title))
return null;
TPage page = TPage.get(db, page_title); if(null == page) return null;
TPage page_word = TPage.get(db, word); if(null == page_word) return null;
TLangPOS[] lp = TLangPOS.get(db, page);
for(TLangPOS lang_pos : lp) {
TMeaning[] tm = TMeaning.get(db, lang_pos);
for(TMeaning tmeaning : tm) {
TRelation[] tr = TRelation.get(db, tmeaning);
for(TRelation trelation : tr) {
TPage p = TRelation.getWikifiedPage(db, trelation);
if(null != p && word.equals(p.getPageTitle())) {
return trelation.getRelationType();
}
}
}
}
return null;
}
/** Gets type of semantic relation between a pair of word (word1 and word2).
*/
public static Relation getRelationType (SQLiteDatabase db,String word1,String word2) {
Relation r;
if(null == word1 || null == word2
|| word1.length() == 0 || word2.length() == 0)
return null;
r = TRelation.getRelationBetweenPageTitleAndWord(db, word1, word2);
if(null != r)
return r;
r = TRelation.getRelationBetweenPageTitleAndWord(db, word2, word1);
return r;
}
}