blob: 543228185e1fbc63cb550a809ceddb52191c30bf [file] [log] [blame]
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2;
import static com.google.android.exoplayer2.util.Assertions.checkArgument;
import android.os.Bundle;
import androidx.annotation.FloatRange;
import androidx.annotation.IntDef;
import androidx.annotation.IntRange;
import androidx.annotation.Nullable;
import com.google.common.base.Objects;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** A rating expressed as a fractional number of stars. */
public final class StarRating extends Rating {
@IntRange(from = 1)
private final int maxStars;
private final float starRating;
/**
* Creates a unrated instance with {@code maxStars}. If {@code maxStars} is not a positive
* integer, it will throw an {@link IllegalArgumentException}.
*
* @param maxStars The maximum number of stars this rating can have.
*/
public StarRating(@IntRange(from = 1) int maxStars) {
checkArgument(maxStars > 0, "maxStars must be a positive integer");
this.maxStars = maxStars;
starRating = RATING_UNSET;
}
/**
* Creates a rated instance with {@code maxStars} and the given fractional number of stars.
* Non-integer values may be used to represent an average rating value. If {@code maxStars} is not
* a positive integer or {@code starRating} is out of range, it will throw an {@link
* IllegalArgumentException}.
*
* @param maxStars The maximum number of stars this rating can have.
* @param starRating A fractional number of stars of this rating from {@code 0f} to {@code
* maxStars}.
*/
public StarRating(@IntRange(from = 1) int maxStars, @FloatRange(from = 0.0) float starRating) {
checkArgument(maxStars > 0, "maxStars must be a positive integer");
checkArgument(
starRating >= 0.0f && starRating <= maxStars, "starRating is out of range [0, maxStars]");
this.maxStars = maxStars;
this.starRating = starRating;
}
@Override
public boolean isRated() {
return starRating != RATING_UNSET;
}
/** Returns the maximum number of stars. Must be a positive number. */
@IntRange(from = 1)
public int getMaxStars() {
return maxStars;
}
/**
* Returns the fractional number of stars of this rating. Will range from {@code 0f} to {@link
* #maxStars}, or {@link #RATING_UNSET} if unrated.
*/
public float getStarRating() {
return starRating;
}
@Override
public int hashCode() {
return Objects.hashCode(maxStars, starRating);
}
@Override
public boolean equals(@Nullable Object obj) {
if (!(obj instanceof StarRating)) {
return false;
}
StarRating other = (StarRating) obj;
return maxStars == other.maxStars && starRating == other.starRating;
}
// Bundleable implementation.
@RatingType private static final int TYPE = RATING_TYPE_STAR;
private static final int MAX_STARS_DEFAULT = 5;
@Documented
@Retention(RetentionPolicy.SOURCE)
@IntDef({FIELD_RATING_TYPE, FIELD_MAX_STARS, FIELD_STAR_RATING})
private @interface FieldNumber {}
private static final int FIELD_MAX_STARS = 1;
private static final int FIELD_STAR_RATING = 2;
@Override
public Bundle toBundle() {
Bundle bundle = new Bundle();
bundle.putInt(keyForField(FIELD_RATING_TYPE), TYPE);
bundle.putInt(keyForField(FIELD_MAX_STARS), maxStars);
bundle.putFloat(keyForField(FIELD_STAR_RATING), starRating);
return bundle;
}
/** Object that can restore a {@link StarRating} from a {@link Bundle}. */
public static final Creator<StarRating> CREATOR = StarRating::fromBundle;
private static StarRating fromBundle(Bundle bundle) {
checkArgument(
bundle.getInt(keyForField(FIELD_RATING_TYPE), /* defaultValue= */ RATING_TYPE_DEFAULT)
== TYPE);
int maxStars =
bundle.getInt(keyForField(FIELD_MAX_STARS), /* defaultValue= */ MAX_STARS_DEFAULT);
float starRating =
bundle.getFloat(keyForField(FIELD_STAR_RATING), /* defaultValue= */ RATING_UNSET);
return starRating == RATING_UNSET
? new StarRating(maxStars)
: new StarRating(maxStars, starRating);
}
private static String keyForField(@FieldNumber int field) {
return Integer.toString(field, Character.MAX_RADIX);
}
}