1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package android.support.v7.media;
17
18import android.content.IntentFilter;
19import android.os.Bundle;
20
21import java.util.ArrayList;
22import java.util.Arrays;
23import java.util.Collection;
24import java.util.Collections;
25import java.util.List;
26
27/**
28 * Describes the state of a media route provider and the routes that it publishes.
29 * <p>
30 * This object is immutable once created using a {@link Builder} instance.
31 * </p>
32 */
33public final class MediaRouteProviderDescriptor {
34    private static final String KEY_ROUTES = "routes";
35
36    private final Bundle mBundle;
37    private List<MediaRouteDescriptor> mRoutes;
38
39    private MediaRouteProviderDescriptor(Bundle bundle,
40            List<MediaRouteDescriptor> routes) {
41        mBundle = bundle;
42        mRoutes = routes;
43    }
44
45    /**
46     * Gets the list of all routes that this provider has published.
47     */
48    public List<MediaRouteDescriptor> getRoutes() {
49        ensureRoutes();
50        return mRoutes;
51    }
52
53    private void ensureRoutes() {
54        if (mRoutes == null) {
55            ArrayList<Bundle> routeBundles = mBundle.<Bundle>getParcelableArrayList(KEY_ROUTES);
56            if (routeBundles == null || routeBundles.isEmpty()) {
57                mRoutes = Collections.<MediaRouteDescriptor>emptyList();
58            } else {
59                final int count = routeBundles.size();
60                mRoutes = new ArrayList<MediaRouteDescriptor>(count);
61                for (int i = 0; i < count; i++) {
62                    mRoutes.add(MediaRouteDescriptor.fromBundle(routeBundles.get(i)));
63                }
64            }
65        }
66    }
67
68    /**
69     * Returns true if the route provider descriptor and all of the routes that
70     * it contains have all of the required fields.
71     * <p>
72     * This verification is deep.  If the provider descriptor is known to be
73     * valid then it is not necessary to call {@link #isValid} on each of its routes.
74     * </p>
75     */
76    public boolean isValid() {
77        ensureRoutes();
78        final int routeCount = mRoutes.size();
79        for (int i = 0; i < routeCount; i++) {
80            MediaRouteDescriptor route = mRoutes.get(i);
81            if (route == null || !route.isValid()) {
82                return false;
83            }
84        }
85        return true;
86    }
87
88    @Override
89    public String toString() {
90        StringBuilder result = new StringBuilder();
91        result.append("MediaRouteProviderDescriptor{ ");
92        result.append("routes=").append(
93                Arrays.toString(getRoutes().toArray()));
94        result.append(", isValid=").append(isValid());
95        result.append(" }");
96        return result.toString();
97    }
98
99    /**
100     * Converts this object to a bundle for serialization.
101     *
102     * @return The contents of the object represented as a bundle.
103     */
104    public Bundle asBundle() {
105        return mBundle;
106    }
107
108    /**
109     * Creates an instance from a bundle.
110     *
111     * @param bundle The bundle, or null if none.
112     * @return The new instance, or null if the bundle was null.
113     */
114    public static MediaRouteProviderDescriptor fromBundle(Bundle bundle) {
115        return bundle != null ? new MediaRouteProviderDescriptor(bundle, null) : null;
116    }
117
118    /**
119     * Builder for {@link MediaRouteProviderDescriptor media route provider descriptors}.
120     */
121    public static final class Builder {
122        private final Bundle mBundle;
123        private ArrayList<MediaRouteDescriptor> mRoutes;
124
125        /**
126         * Creates an empty media route provider descriptor builder.
127         */
128        public Builder() {
129            mBundle = new Bundle();
130        }
131
132        /**
133         * Creates a media route provider descriptor builder whose initial contents are
134         * copied from an existing descriptor.
135         */
136        public Builder(MediaRouteProviderDescriptor descriptor) {
137            if (descriptor == null) {
138                throw new IllegalArgumentException("descriptor must not be null");
139            }
140
141            mBundle = new Bundle(descriptor.mBundle);
142
143            descriptor.ensureRoutes();
144            if (!descriptor.mRoutes.isEmpty()) {
145                mRoutes = new ArrayList<MediaRouteDescriptor>(descriptor.mRoutes);
146            }
147        }
148
149        /**
150         * Adds a route.
151         */
152        public Builder addRoute(MediaRouteDescriptor route) {
153            if (route == null) {
154                throw new IllegalArgumentException("route must not be null");
155            }
156
157            if (mRoutes == null) {
158                mRoutes = new ArrayList<MediaRouteDescriptor>();
159            } else if (mRoutes.contains(route)) {
160                throw new IllegalArgumentException("route descriptor already added");
161            }
162            mRoutes.add(route);
163            return this;
164        }
165
166        /**
167         * Adds a list of routes.
168         */
169        public Builder addRoutes(Collection<MediaRouteDescriptor> routes) {
170            if (routes == null) {
171                throw new IllegalArgumentException("routes must not be null");
172            }
173
174            if (!routes.isEmpty()) {
175                for (MediaRouteDescriptor route : routes) {
176                    addRoute(route);
177                }
178            }
179            return this;
180        }
181
182        /**
183         * Builds the {@link MediaRouteProviderDescriptor media route provider descriptor}.
184         */
185        public MediaRouteProviderDescriptor build() {
186            if (mRoutes != null) {
187                final int count = mRoutes.size();
188                ArrayList<Bundle> routeBundles = new ArrayList<Bundle>(count);
189                for (int i = 0; i < count; i++) {
190                    routeBundles.add(mRoutes.get(i).asBundle());
191                }
192                mBundle.putParcelableArrayList(KEY_ROUTES, routeBundles);
193            }
194            return new MediaRouteProviderDescriptor(mBundle, mRoutes);
195        }
196    }
197}