Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b2a23513 authored by Chulwoo Lee's avatar Chulwoo Lee
Browse files

Encode/Decode genres using CSV

Currently, the delimiter of genres is comma, but it is also used in the
broadcast genre, so we decided to encode the genre to CSV format.
Let's support only a simple CSV not a complex cases like fully double
quoted string to simplify the encode/decode method and encourage the
TIS to use these methods for broadcast genres.

Bug: 25241891
Change-Id: Id745d4fee43dbcdc508c0f6fad83477b6209ecd8
parent 93f04f89
Loading
Loading
Loading
Loading
+78 −16
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.IBinder;
import android.provider.BaseColumns;
import android.provider.BaseColumns;
import android.util.ArraySet;
import android.util.ArraySet;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
@@ -1020,22 +1021,28 @@ public final class TvContract {
         *
         *
         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
         * {@link Genres#encode} to create a text that can be stored in this column. Use
         * {@link Genres#decode} to get the broadcast genre strings from the text stored in the
         * column.
         *
         *
         * <p>Type: TEXT
         * <p>Type: TEXT
         * @see Genres#encode
         * @see Genres#decode
         */
         */
        public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
        public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";


        /**
        /**
         * The comma-separated canonical genre string of this TV program.
         * The comma-separated canonical genre string of this TV program.
         *
         *
         * <p>Canonical genres are defined in {@link Genres}. Use
         * <p>Canonical genres are defined in {@link Genres}. Use {@link Genres#encode} to create a
         * {@link Genres#encode Genres.encode()} to create a text that can be stored in this column.
         * text that can be stored in this column. Use {@link Genres#decode} to get the canonical
         * Use {@link Genres#decode Genres.decode()} to get the canonical genre strings from the
         * genre strings from the text stored in the column.
         * text stored in this column.
         *
         *
         * <p>Type: TEXT
         * <p>Type: TEXT
         * @see Genres
         * @see Genres
         * @see Genres#encode
         * @see Genres#decode
         */
         */
        public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
        public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";


@@ -1303,34 +1310,86 @@ public final class TvContract {
                CANONICAL_GENRES.add(TECH_SCIENCE);
                CANONICAL_GENRES.add(TECH_SCIENCE);
            }
            }


            private static final char DOUBLE_QUOTE = '"';
            private static final char COMMA = ',';

            private Genres() {}
            private Genres() {}


            /**
            /**
             * Encodes canonical genre strings to a text that can be put into the database.
             * Encodes genre strings to a text that can be put into the database.
             *
             *
             * @param genres Canonical genre strings. Use the strings defined in this class.
             * @param genres Genre strings.
             * @return an encoded genre string that can be inserted into the
             * @return an encoded genre string that can be inserted into the
             *         {@link #COLUMN_CANONICAL_GENRE} column.
             *         {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
             */
             */
            public static String encode(String... genres) {
            public static String encode(String... genres) {
                StringBuilder sb = new StringBuilder();
                StringBuilder sb = new StringBuilder();
                String separator = "";
                String separator = "";
                for (String genre : genres) {
                for (String genre : genres) {
                    sb.append(separator).append(genre);
                    sb.append(separator).append(encodeToCsv(genre));
                    separator = ",";
                    separator = COMMA;
                }
                return sb.toString();
            }

            private static String encodeToCsv(String genre) {
                StringBuilder sb = new StringBuilder();
                int length = genre.length();
                for (int i = 0; i < length; ++i) {
                    char c = genre.charAt(i);
                    switch (c) {
                        case DOUBLE_QUOTE:
                            sb.append(DOUBLE_QUOTE);
                            break;
                        case COMMA:
                            sb.append(DOUBLE_QUOTE);
                            break;
                    }
                    sb.append(c);
                }
                }
                return sb.toString();
                return sb.toString();
            }
            }


            /**
            /**
             * Decodes the canonical genre strings from the text stored in the database.
             * Decodes the genre strings from the text stored in the database.
             *
             *
             * @param genres The encoded genre string retrieved from the
             * @param genres The encoded genre string retrieved from the
             *            {@link #COLUMN_CANONICAL_GENRE} column.
             *            {@link #COLUMN_BROADCAST_GENRE} or {@link #COLUMN_CANONICAL_GENRE} column.
             * @return canonical genre strings.
             * @return genre strings.
             */
             */
            public static String[] decode(String genres) {
            public static String[] decode(String genres) {
                return genres.split("\\s*,\\s*");
                StringBuilder sb = new StringBuilder();
                List<String> results = new ArrayList<>();
                int length = genres.length();
                boolean escape = false;
                for (int i = 0; i < length; ++i) {
                    char c = genres.charAt(i);
                    switch (c) {
                        case DOUBLE_QUOTE:
                            if (!escape) {
                                escape = true;
                                continue;
                            }
                            break;
                        case COMMA:
                            if (!escape) {
                                String string = sb.toString().trim();
                                if (string.length() > 0) {
                                    results.add(string);
                                }
                                sb = new StringBuilder();
                                continue;
                            }
                            break;
                    }
                    sb.append(c);
                    escape = false;
                }
                String string = sb.toString().trim();
                if (string.length() > 0) {
                    results.add(string);
                }
                return results.toArray(new String[results.size()]);
            }
            }


            /**
            /**
@@ -1441,7 +1500,10 @@ public final class TvContract {
         *
         *
         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
         * <p>Use the same language appeared in the underlying broadcast standard, if applicable.
         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
         * (For example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
         * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty. Use
         * {@link Genres#encode Genres.encode()} to create a text that can be stored in this column.
         * Use {@link Genres#decode Genres.decode()} to get the broadcast genre strings from the
         * text stored in the column.
         *
         *
         * <p>Type: TEXT
         * <p>Type: TEXT
         * @see Programs#COLUMN_BROADCAST_GENRE
         * @see Programs#COLUMN_BROADCAST_GENRE
@@ -1454,7 +1516,7 @@ public final class TvContract {
         * <p>Canonical genres are defined in {@link Programs.Genres}. Use
         * <p>Canonical genres are defined in {@link Programs.Genres}. Use
         * {@link Programs.Genres#encode Genres.encode()} to create a text that can be stored in
         * {@link Programs.Genres#encode Genres.encode()} to create a text that can be stored in
         * this column. Use {@link Programs.Genres#decode Genres.decode()} to get the canonical
         * this column. Use {@link Programs.Genres#decode Genres.decode()} to get the canonical
         * genre strings from the text stored in this column.
         * genre strings from the text stored in the column.
         *
         *
         * <p>Type: TEXT
         * <p>Type: TEXT
         * @see Programs#COLUMN_CANONICAL_GENRE
         * @see Programs#COLUMN_CANONICAL_GENRE