示例#1
0
        /// <summary>
        /// Reads the radicals from the radicals file.
        /// </summary>
        /// <param name="directoryPath">Path to the base directory of the set.</param>
        /// <returns>Radicals read.</returns>
        protected override ExtendedRadical[] DoReadData(string directoryPath)
        {
            List <ExtendedRadical> extendedRadicals = new List <ExtendedRadical>();
            string radicalsFilePath = Path.Combine(directoryPath, RadicalsFilePath);

            XDocument xdoc  = XDocument.Load(radicalsFilePath);
            XElement  xroot = xdoc.Root;

            // Get radicals from DB.
            RadicalEntity[] radicals = _radicalDao.GetAllRadicals().ToArray();

            foreach (XElement xradical in xroot.Elements(XmlNode_Radical))
            {
                List <RadicalGroup> groups = new List <RadicalGroup>();

                // Try to read the standard form.
                XElement xgroups = xradical.Element(XmlNode_RadicalGroups);
                if (xgroups != null)
                {
                    // Read the groups.
                    foreach (XElement xgroup in xgroups.Elements(XmlNode_RadicalGroup))
                    {
                        RadicalGroup         group         = new RadicalGroup();
                        List <RadicalEntity> groupRadicals = new List <RadicalEntity>();
                        // Read the group items.
                        foreach (XElement xitem in xgroup.Elements(XmlNode_RadicalGroupItem))
                        {
                            string radicalCharacter =
                                xitem.ReadAttributeString(XmlAttribute_Radical);

                            // Find the matching radical.
                            if (!string.IsNullOrWhiteSpace(radicalCharacter))
                            {
                                RadicalEntity radical = radicals.Where(
                                    r => r.Character == radicalCharacter).FirstOrDefault();
                                if (radical != null)
                                {
                                    groupRadicals.Add(radical);
                                }
                            }
                        }

                        // Finalize and add the radical group.
                        if (groupRadicals.Any())
                        {
                            group.Radicals = groupRadicals.ToArray();
                            groups.Add(group);
                        }
                    }
                }
                else
                {
                    // Try to read the short form.

                    // Start by reading the radical character.
                    string radicalCharacter = xradical
                                              .ReadAttributeString(XmlAttribute_Character);

                    // Find the matching radical.
                    if (!string.IsNullOrWhiteSpace(radicalCharacter))
                    {
                        RadicalEntity radical = radicals.Where(
                            r => r.Character == radicalCharacter).FirstOrDefault();
                        if (radical != null)
                        {
                            groups.Add(new RadicalGroup()
                            {
                                Radicals = new RadicalEntity[1] {
                                    radical
                                }
                            });
                        }
                    }
                }

                // Build the extended radical and return it.
                if (groups.Any())
                {
                    // Read the attributes.
                    string name        = xradical.ReadAttributeString(XmlAttribute_Name);
                    string imageSource = xradical.ReadAttributeString(XmlAttribute_ImageSource);
                    if (imageSource != null)
                    {
                        string fullPath = Path.GetFullPath(Path.Combine(directoryPath, imageSource));
                        if (File.Exists(fullPath))
                        {
                            imageSource = new Uri(fullPath).ToString();
                        }
                        else
                        {
                            imageSource = null;
                        }
                    }
                    string character = xradical.ReadAttributeString(XmlAttribute_Character);

                    ExtendedRadical extendedRadical = new ExtendedRadical();
                    extendedRadical.Character     = character;
                    extendedRadical.ImageUri      = imageSource;
                    extendedRadical.Name          = name;
                    extendedRadical.RadicalGroups = groups.ToArray();

                    // Get frequency.
                    int frequency = 0;
                    foreach (RadicalGroup group in extendedRadical.RadicalGroups)
                    {
                        foreach (RadicalEntity r in group.Radicals)
                        {
                            frequency += r.Kanji.Count;
                        }
                        // Not very exact (the AND link between groups is not taken in account)
                        // but let's do this anyway.
                        //todo: Compute exact value.
                    }
                    extendedRadical.Frequency = frequency;
                    extendedRadicals.Add(extendedRadical);
                }
            }

            return(extendedRadicals.ToArray());
        }
示例#2
0
        /// <summary>
        /// Builds the SQL filter clauses to retrieve filtered kanji.
        /// </summary>
        internal static string BuildKanjiFilterClauses(List <DaoParameter> parameters, RadicalGroup[] radicalGroups,
                                                       string textFilter, string meaningFilter, string anyReadingFilter, string onYomiFilter,
                                                       string kunYomiFilter, string nanoriFilter, int jlptLevel, int wkLevel)
        {
            const int minJlptLevel = Levels.MinJlptLevel;
            const int maxJlptLevel = Levels.MaxJlptLevel;
            const int minWkLevel   = Levels.MinWkLevel;
            const int maxWkLevel   = Levels.MaxWkLevel;

            string sqlJlptFilter = string.Empty;

            if (jlptLevel >= minJlptLevel && jlptLevel <= maxJlptLevel)
            {
                sqlJlptFilter = string.Format("k.{0}=@jlpt ",
                                              SqlHelper.Field_Vocab_JlptLevel);

                parameters.Add(new DaoParameter("@jlpt", jlptLevel));
            }
            else if (jlptLevel < minJlptLevel)
            {
                sqlJlptFilter = string.Format("k.{0} IS NULL ",
                                              SqlHelper.Field_Vocab_JlptLevel);
            }

            string sqlWkFilter = string.Empty;

            if (wkLevel >= minWkLevel && wkLevel <= maxWkLevel)
            {
                sqlWkFilter = string.Format("k.{0}=@wk ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);

                parameters.Add(new DaoParameter("@wk", wkLevel));
            }
            else if (wkLevel > maxWkLevel)
            {
                sqlWkFilter = string.Format("k.{0} IS NULL ",
                                            SqlHelper.Field_Vocab_WaniKaniLevel);
            }

            string sqlTextFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(textFilter))
            {
                // Build the text filter.
                // Example with textFilter="年生まれ" :
                //
                // WHERE '1959年生まれ' LIKE '%' || k.Character || '%'

                sqlTextFilter = string.Format("@textFilter LIKE '%' || k.{0} || '%' ",
                                              SqlHelper.Field_Kanji_Character);

                // And add the parameter.
                parameters.Add(new DaoParameter("@textFilter", textFilter));
            }

            string sqlAnyReadingFilter = string.Empty;
            string sqlOnYomiFilter     = string.Empty;
            string sqlKunYomiFilter    = string.Empty;
            string sqlNanoriFilter     = string.Empty;

            if (!string.IsNullOrWhiteSpace(anyReadingFilter))
            {
                // Build the any reading filter.
                // Example with anyReadingFilter="test" :
                //
                // WHERE (k.KunYomi LIKE '%test%' OR k.OnYomi LIKE '%test%'
                // OR k.Nanori LIKE '%test%')

                sqlAnyReadingFilter = string.Format(
                    "(k.{0} LIKE @anyReadingFilter OR k.{1} LIKE @anyReadingFilter OR k.{2} LIKE @anyReadingFilter) ",
                    SqlHelper.Field_Kanji_KunYomi,
                    SqlHelper.Field_Kanji_OnYomi,
                    SqlHelper.Field_Kanji_Nanori);

                // And add the parameter.
                parameters.Add(new DaoParameter("@anyReadingFilter", string.Format("%{0}%", anyReadingFilter)));
            }
            else
            {
                // Any reading filter is not set. Browse the other reading filters.
                if (!string.IsNullOrWhiteSpace(onYomiFilter))
                {
                    sqlOnYomiFilter = string.Format("k.{0} LIKE @onYomiFilter ", SqlHelper.Field_Kanji_OnYomi);

                    parameters.Add(new DaoParameter("@onYomiFilter", string.Format("%{0}%", onYomiFilter)));
                }
                if (!string.IsNullOrWhiteSpace(kunYomiFilter))
                {
                    sqlKunYomiFilter = string.Format("k.{0} LIKE @kunYomiFilter ", SqlHelper.Field_Kanji_KunYomi);

                    parameters.Add(new DaoParameter("@kunYomiFilter", string.Format("%{0}%", kunYomiFilter)));
                }
                if (!string.IsNullOrWhiteSpace(nanoriFilter))
                {
                    sqlNanoriFilter = string.Format("k.{0} LIKE @nanoriFilter ", SqlHelper.Field_Kanji_Nanori);

                    parameters.Add(new DaoParameter("@nanoriFilter", string.Format("%{0}%", nanoriFilter)));
                }
            }

            StringBuilder sqlRadicalFilter = new StringBuilder();

            if (radicalGroups.Any())
            {
                // Build the radical sql filter. For example with:
                // [0] = { 7974, 7975 }
                // [1] = { 7976 }
                // [2] = { 7977 }
                // ... we would want something like:
                //
                //WHERE (SELECT COUNT(*)
                //     FROM
                //     (
                //         SELECT 7976 UNION SELECT 7977
                //         INTERSECT
                //         SELECT kr.Radicals_Id
                //         FROM KanjiRadical kr
                //         WHERE kr.Kanji_Id = k.Id
                //     ))=2
                //     AND (SELECT COUNT(*)
                //     FROM
                //     (
                //         SELECT 7974 UNION SELECT 7975
                //         INTERSECT
                //         SELECT kr.Radicals_Id
                //         FROM KanjiRadical kr
                //         WHERE kr.Kanji_Id = k.Id
                //     )) >= 1

                // Get the mandatory radicals. In our example, these would be {7976,7977}.
                RadicalEntity[] mandatoryRadicals = radicalGroups
                                                    .Where(g => g.Radicals.Count() == 1)
                                                    .SelectMany(g => g.Radicals).ToArray();

                // Get the other radical groups. In our example, this would be {{7974,7975}}.
                RadicalGroup[] optionGroups = radicalGroups.Where(g => g.Radicals.Length > 1).ToArray();

                // We need to build one request per option group,
                // and one request for all mandatory radicals.
                int idParamIndex = 0;

                // Start with the request for all mandatory radicals.
                bool hasMandatoryRadicals = mandatoryRadicals.Any();
                if (hasMandatoryRadicals)
                {
                    sqlRadicalFilter.Append("(SELECT COUNT(*) FROM (");
                    for (int i = 0; i < mandatoryRadicals.Length; i++)
                    {
                        RadicalEntity radical = mandatoryRadicals[i];
                        sqlRadicalFilter.AppendFormat("SELECT @rid{0} ", idParamIndex);
                        if (i < mandatoryRadicals.Length - 1)
                        {
                            sqlRadicalFilter.Append("UNION ");
                        }
                        parameters.Add(new DaoParameter("@rid" + idParamIndex++, radical.ID));
                    }
                    sqlRadicalFilter.AppendFormat(
                        "INTERSECT SELECT kr.{0} FROM {1} kr WHERE kr.{2}=k.{3}))=@radicalsCount ",
                        SqlHelper.Field_Kanji_Radical_RadicalId,
                        SqlHelper.Table_Kanji_Radical,
                        SqlHelper.Field_Kanji_Radical_KanjiId,
                        SqlHelper.Field_Kanji_Id);
                    parameters.Add(new DaoParameter("@radicalsCount", mandatoryRadicals.Count()));
                }

                // Now build the requests for the option groups.
                for (int i = 0; i < optionGroups.Length; i++)
                {
                    RadicalGroup optionGroup = optionGroups[i];
                    if (hasMandatoryRadicals || i > 0)
                    {
                        sqlRadicalFilter.Append("AND ");
                    }

                    sqlRadicalFilter.Append("(SELECT COUNT(*) FROM (");
                    foreach (RadicalEntity radical in optionGroup.Radicals)
                    {
                        sqlRadicalFilter.AppendFormat("SELECT @rid{0} ", idParamIndex);
                        if (optionGroup.Radicals.Last() != radical)
                        {
                            sqlRadicalFilter.Append("UNION ");
                        }
                        parameters.Add(new DaoParameter("@rid" + idParamIndex++, radical.ID));
                    }
                    sqlRadicalFilter.AppendFormat(
                        "INTERSECT SELECT kr.{0} FROM {1} kr WHERE kr.{2}=k.{3}))>=1 ",
                        SqlHelper.Field_Kanji_Radical_RadicalId,
                        SqlHelper.Table_Kanji_Radical,
                        SqlHelper.Field_Kanji_Radical_KanjiId,
                        SqlHelper.Field_Kanji_Id);
                }
            }

            string sqlMeaningFilter = string.Empty;

            if (!string.IsNullOrWhiteSpace(meaningFilter))
            {
                // Build the meaning filter.
                // Example with meaningFilter="test" :
                //
                // WHERE EXISTS (SELECT * FROM KanjiMeaningSet km
                // WHERE km.Kanji_Id=k.Id AND km.Language IS NULL
                // AND km.Meaning LIKE '%test%')

                sqlMeaningFilter = string.Format(
                    "k.{0} IN (SELECT km.{1} FROM {2} km WHERE km.{3} IS NULL AND km.{4} LIKE @meaningFilter) ",
                    SqlHelper.Field_Kanji_Id,
                    SqlHelper.Field_KanjiMeaning_KanjiId,
                    SqlHelper.Table_KanjiMeaning,
                    SqlHelper.Field_KanjiMeaning_Language,
                    SqlHelper.Field_KanjiMeaning_Meaning);

                // And add the parameter.
                parameters.Add(new DaoParameter("@meaningFilter", "%" + meaningFilter + "%"));
            }

            string[] sqlArgs =
            {
                sqlJlptFilter,
                sqlWkFilter,
                sqlTextFilter,
                sqlAnyReadingFilter,
                sqlOnYomiFilter,
                sqlKunYomiFilter,
                sqlNanoriFilter,
                sqlRadicalFilter.ToString(),
                sqlMeaningFilter
            };

            bool isFiltered = false;

            for (int i = 0; i < sqlArgs.Length; i++)
            {
                string arg = sqlArgs[i];
                if (string.IsNullOrEmpty(arg) || arg.StartsWith("JOIN"))
                {
                    continue;
                }

                sqlArgs[i] = (isFiltered ? "AND " : "WHERE ") + arg;
                isFiltered = true;
            }

            return(string.Concat(sqlArgs));
        }