All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.projectnessie.versioned.persist.adapter.ImmutableCommitAttempt Maven / Gradle / Ivy

package org.projectnessie.versioned.persist.adapter;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.errorprone.annotations.Var;
import com.google.protobuf.ByteString;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import javax.annotation.concurrent.NotThreadSafe;
import org.immutables.value.Generated;
import org.projectnessie.versioned.BranchName;
import org.projectnessie.versioned.Hash;
import org.projectnessie.versioned.Key;

/**
 * Immutable implementation of {@link CommitAttempt}.
 * 

* Use the builder to create immutable instances: * {@code ImmutableCommitAttempt.builder()}. */ @Generated(from = "CommitAttempt", generator = "Immutables") @SuppressWarnings({"all"}) @ParametersAreNonnullByDefault @javax.annotation.Generated("org.immutables.processor.ProxyProcessor") @Immutable @CheckReturnValue public final class ImmutableCommitAttempt implements CommitAttempt { private final BranchName commitToBranch; private final Optional expectedHead; private final ImmutableMap> expectedStates; private final ImmutableList puts; private final ImmutableMap global; private final ImmutableList unchanged; private final ImmutableList deletes; private final ByteString commitMetaSerialized; private ImmutableCommitAttempt(ImmutableCommitAttempt.Builder builder) { this.commitToBranch = builder.commitToBranch; this.expectedStates = builder.expectedStates.build(); this.puts = builder.puts.build(); this.global = builder.global.build(); this.unchanged = builder.unchanged.build(); this.deletes = builder.deletes.build(); this.commitMetaSerialized = builder.commitMetaSerialized; this.expectedHead = builder.expectedHead != null ? builder.expectedHead : Objects.requireNonNull(CommitAttempt.super.getExpectedHead(), "expectedHead"); } private ImmutableCommitAttempt( BranchName commitToBranch, Optional expectedHead, ImmutableMap> expectedStates, ImmutableList puts, ImmutableMap global, ImmutableList unchanged, ImmutableList deletes, ByteString commitMetaSerialized) { this.commitToBranch = commitToBranch; this.expectedHead = expectedHead; this.expectedStates = expectedStates; this.puts = puts; this.global = global; this.unchanged = unchanged; this.deletes = deletes; this.commitMetaSerialized = commitMetaSerialized; } /** * Branch to commit to. If {@link #getExpectedHead()} is present, the referenced branch's HEAD * must be equal to this hash. */ @Override public BranchName getCommitToBranch() { return commitToBranch; } /** *Expected HEAD of {@link #getCommitToBranch()}. */ @Override public Optional getExpectedHead() { return expectedHead; } /** * Mapping of content-ids to expected global content-state (think: Iceberg table-metadata), coming * from the "expected-state" property of a {@code PutGlobal} commit operation. */ @Override public ImmutableMap> getExpectedStates() { return expectedStates; } /** * List of all {@code Put} operations, with their keys, content-types and serialized {@code * Content}. */ @Override public ImmutableList getPuts() { return puts; } /** * Mapping of content-ids to the new content-state (think: Iceberg table-metadata), coming from * the "content" property of a {@code PutGlobal} commit operation. */ @Override public ImmutableMap getGlobal() { return global; } /** *List of "unchanged" keys, from {@code Unchanged} commit operations. */ @Override public ImmutableList getUnchanged() { return unchanged; } /** *List of "unchanged" keys, from {@code Delete} commit operations. */ @Override public ImmutableList getDeletes() { return deletes; } /** *Serialized commit-metadata. */ @Override public ByteString getCommitMetaSerialized() { return commitMetaSerialized; } /** * Copy the current immutable object by setting a value for the {@link CommitAttempt#getCommitToBranch() commitToBranch} attribute. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param value A new value for commitToBranch * @return A modified copy of the {@code this} object */ public final ImmutableCommitAttempt withCommitToBranch(BranchName value) { if (this.commitToBranch == value) return this; BranchName newValue = Objects.requireNonNull(value, "commitToBranch"); return new ImmutableCommitAttempt( newValue, this.expectedHead, this.expectedStates, this.puts, this.global, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object by setting a value for the {@link CommitAttempt#getExpectedHead() expectedHead} attribute. * An equals check used to prevent copying of the same value by returning {@code this}. * @param value A new value for expectedHead * @return A modified copy of the {@code this} object */ public final ImmutableCommitAttempt withExpectedHead(Optional value) { Optional newValue = Objects.requireNonNull(value, "expectedHead"); if (this.expectedHead.equals(newValue)) return this; return new ImmutableCommitAttempt( this.commitToBranch, newValue, this.expectedStates, this.puts, this.global, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object by replacing the {@link CommitAttempt#getExpectedStates() expectedStates} map with the specified map. * Nulls are not permitted as keys or values. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param entries The entries to be added to the expectedStates map * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withExpectedStates(Map> entries) { if (this.expectedStates == entries) return this; ImmutableMap> newValue = ImmutableMap.copyOf(entries); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, newValue, this.puts, this.global, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getPuts() puts}. * @param elements The elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withPuts(KeyWithBytes... elements) { ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, newValue, this.global, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getPuts() puts}. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param elements An iterable of puts elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withPuts(Iterable elements) { if (this.puts == elements) return this; ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, newValue, this.global, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object by replacing the {@link CommitAttempt#getGlobal() global} map with the specified map. * Nulls are not permitted as keys or values. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param entries The entries to be added to the global map * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withGlobal(Map entries) { if (this.global == entries) return this; ImmutableMap newValue = ImmutableMap.copyOf(entries); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, newValue, this.unchanged, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getUnchanged() unchanged}. * @param elements The elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withUnchanged(Key... elements) { ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, this.global, newValue, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getUnchanged() unchanged}. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param elements An iterable of unchanged elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withUnchanged(Iterable elements) { if (this.unchanged == elements) return this; ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, this.global, newValue, this.deletes, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getDeletes() deletes}. * @param elements The elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withDeletes(Key... elements) { ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, this.global, this.unchanged, newValue, this.commitMetaSerialized); } /** * Copy the current immutable object with elements that replace the content of {@link CommitAttempt#getDeletes() deletes}. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param elements An iterable of deletes elements to set * @return A modified copy of {@code this} object */ public final ImmutableCommitAttempt withDeletes(Iterable elements) { if (this.deletes == elements) return this; ImmutableList newValue = ImmutableList.copyOf(elements); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, this.global, this.unchanged, newValue, this.commitMetaSerialized); } /** * Copy the current immutable object by setting a value for the {@link CommitAttempt#getCommitMetaSerialized() commitMetaSerialized} attribute. * A shallow reference equality check is used to prevent copying of the same value by returning {@code this}. * @param value A new value for commitMetaSerialized * @return A modified copy of the {@code this} object */ public final ImmutableCommitAttempt withCommitMetaSerialized(ByteString value) { if (this.commitMetaSerialized == value) return this; ByteString newValue = Objects.requireNonNull(value, "commitMetaSerialized"); return new ImmutableCommitAttempt( this.commitToBranch, this.expectedHead, this.expectedStates, this.puts, this.global, this.unchanged, this.deletes, newValue); } /** * This instance is equal to all instances of {@code ImmutableCommitAttempt} that have equal attribute values. * @return {@code true} if {@code this} is equal to {@code another} instance */ @Override public boolean equals(@Nullable Object another) { if (this == another) return true; return another instanceof ImmutableCommitAttempt && equalTo((ImmutableCommitAttempt) another); } private boolean equalTo(ImmutableCommitAttempt another) { return commitToBranch.equals(another.commitToBranch) && expectedHead.equals(another.expectedHead) && expectedStates.equals(another.expectedStates) && puts.equals(another.puts) && global.equals(another.global) && unchanged.equals(another.unchanged) && deletes.equals(another.deletes) && commitMetaSerialized.equals(another.commitMetaSerialized); } /** * Computes a hash code from attributes: {@code commitToBranch}, {@code expectedHead}, {@code expectedStates}, {@code puts}, {@code global}, {@code unchanged}, {@code deletes}, {@code commitMetaSerialized}. * @return hashCode value */ @Override public int hashCode() { @Var int h = 5381; h += (h << 5) + commitToBranch.hashCode(); h += (h << 5) + expectedHead.hashCode(); h += (h << 5) + expectedStates.hashCode(); h += (h << 5) + puts.hashCode(); h += (h << 5) + global.hashCode(); h += (h << 5) + unchanged.hashCode(); h += (h << 5) + deletes.hashCode(); h += (h << 5) + commitMetaSerialized.hashCode(); return h; } /** * Prints the immutable value {@code CommitAttempt} with attribute values. * @return A string representation of the value */ @Override public String toString() { return MoreObjects.toStringHelper("CommitAttempt") .omitNullValues() .add("commitToBranch", commitToBranch) .add("expectedHead", expectedHead) .add("expectedStates", expectedStates) .add("puts", puts) .add("global", global) .add("unchanged", unchanged) .add("deletes", deletes) .add("commitMetaSerialized", commitMetaSerialized) .toString(); } /** * Creates an immutable copy of a {@link CommitAttempt} value. * Uses accessors to get values to initialize the new immutable instance. * If an instance is already immutable, it is returned as is. * @param instance The instance to copy * @return A copied immutable CommitAttempt instance */ public static ImmutableCommitAttempt copyOf(CommitAttempt instance) { if (instance instanceof ImmutableCommitAttempt) { return (ImmutableCommitAttempt) instance; } return ImmutableCommitAttempt.builder() .from(instance) .build(); } /** * Creates a builder for {@link ImmutableCommitAttempt ImmutableCommitAttempt}. *

   * ImmutableCommitAttempt.builder()
   *    .commitToBranch(org.projectnessie.versioned.BranchName) // required {@link CommitAttempt#getCommitToBranch() commitToBranch}
   *    .expectedHead(Optional&lt;org.projectnessie.versioned.Hash&gt;) // optional {@link CommitAttempt#getExpectedHead() expectedHead}
   *    .putExpectedStates|putAllExpectedStates(org.projectnessie.versioned.persist.adapter.ContentId => Optional&lt;com.google.protobuf.ByteString&gt;) // {@link CommitAttempt#getExpectedStates() expectedStates} mappings
   *    .addPuts|addAllPuts(org.projectnessie.versioned.persist.adapter.KeyWithBytes) // {@link CommitAttempt#getPuts() puts} elements
   *    .putGlobal|putAllGlobal(org.projectnessie.versioned.persist.adapter.ContentId => com.google.protobuf.ByteString) // {@link CommitAttempt#getGlobal() global} mappings
   *    .addUnchanged|addAllUnchanged(org.projectnessie.versioned.Key) // {@link CommitAttempt#getUnchanged() unchanged} elements
   *    .addDeletes|addAllDeletes(org.projectnessie.versioned.Key) // {@link CommitAttempt#getDeletes() deletes} elements
   *    .commitMetaSerialized(com.google.protobuf.ByteString) // required {@link CommitAttempt#getCommitMetaSerialized() commitMetaSerialized}
   *    .build();
   * 
* @return A new ImmutableCommitAttempt builder */ public static ImmutableCommitAttempt.Builder builder() { return new ImmutableCommitAttempt.Builder(); } /** * Builds instances of type {@link ImmutableCommitAttempt ImmutableCommitAttempt}. * Initialize attributes and then invoke the {@link #build()} method to create an * immutable instance. *

{@code Builder} is not thread-safe and generally should not be stored in a field or collection, * but instead used immediately to create instances. */ @Generated(from = "CommitAttempt", generator = "Immutables") @NotThreadSafe public static final class Builder { private static final long INIT_BIT_COMMIT_TO_BRANCH = 0x1L; private static final long INIT_BIT_COMMIT_META_SERIALIZED = 0x2L; private long initBits = 0x3L; private @Nullable BranchName commitToBranch; private @Nullable Optional expectedHead; private ImmutableMap.Builder> expectedStates = ImmutableMap.builder(); private ImmutableList.Builder puts = ImmutableList.builder(); private ImmutableMap.Builder global = ImmutableMap.builder(); private ImmutableList.Builder unchanged = ImmutableList.builder(); private ImmutableList.Builder deletes = ImmutableList.builder(); private @Nullable ByteString commitMetaSerialized; private Builder() { } /** * Fill a builder with attribute values from the provided {@code CommitAttempt} instance. * Regular attribute values will be replaced with those from the given instance. * Absent optional values will not replace present values. * Collection elements and entries will be added, not replaced. * @param instance The instance from which to copy values * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder from(CommitAttempt instance) { Objects.requireNonNull(instance, "instance"); commitToBranch(instance.getCommitToBranch()); expectedHead(instance.getExpectedHead()); putAllExpectedStates(instance.getExpectedStates()); addAllPuts(instance.getPuts()); putAllGlobal(instance.getGlobal()); addAllUnchanged(instance.getUnchanged()); addAllDeletes(instance.getDeletes()); commitMetaSerialized(instance.getCommitMetaSerialized()); return this; } /** * Initializes the value for the {@link CommitAttempt#getCommitToBranch() commitToBranch} attribute. * @param commitToBranch The value for commitToBranch * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder commitToBranch(BranchName commitToBranch) { this.commitToBranch = Objects.requireNonNull(commitToBranch, "commitToBranch"); initBits &= ~INIT_BIT_COMMIT_TO_BRANCH; return this; } /** * Initializes the value for the {@link CommitAttempt#getExpectedHead() expectedHead} attribute. *

If not set, this attribute will have a default value as returned by the initializer of {@link CommitAttempt#getExpectedHead() expectedHead}. * @param expectedHead The value for expectedHead * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder expectedHead(Optional expectedHead) { this.expectedHead = Objects.requireNonNull(expectedHead, "expectedHead"); return this; } /** * Put one entry to the {@link CommitAttempt#getExpectedStates() expectedStates} map. * @param key The key in the expectedStates map * @param value The associated value in the expectedStates map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putExpectedStates(ContentId key, Optional value) { this.expectedStates.put(key, value); return this; } /** * Put one entry to the {@link CommitAttempt#getExpectedStates() expectedStates} map. Nulls are not permitted * @param entry The key and value entry * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putExpectedStates(Map.Entry> entry) { this.expectedStates.put(entry); return this; } /** * Sets or replaces all mappings from the specified map as entries for the {@link CommitAttempt#getExpectedStates() expectedStates} map. Nulls are not permitted * @param entries The entries that will be added to the expectedStates map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder expectedStates(Map> entries) { this.expectedStates = ImmutableMap.builder(); return putAllExpectedStates(entries); } /** * Put all mappings from the specified map as entries to {@link CommitAttempt#getExpectedStates() expectedStates} map. Nulls are not permitted * @param entries The entries that will be added to the expectedStates map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putAllExpectedStates(Map> entries) { this.expectedStates.putAll(entries); return this; } /** * Adds one element to {@link CommitAttempt#getPuts() puts} list. * @param element A puts element * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addPuts(KeyWithBytes element) { this.puts.add(element); return this; } /** * Adds elements to {@link CommitAttempt#getPuts() puts} list. * @param elements An array of puts elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addPuts(KeyWithBytes... elements) { this.puts.add(elements); return this; } /** * Sets or replaces all elements for {@link CommitAttempt#getPuts() puts} list. * @param elements An iterable of puts elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder puts(Iterable elements) { this.puts = ImmutableList.builder(); return addAllPuts(elements); } /** * Adds elements to {@link CommitAttempt#getPuts() puts} list. * @param elements An iterable of puts elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addAllPuts(Iterable elements) { this.puts.addAll(elements); return this; } /** * Put one entry to the {@link CommitAttempt#getGlobal() global} map. * @param key The key in the global map * @param value The associated value in the global map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putGlobal(ContentId key, ByteString value) { this.global.put(key, value); return this; } /** * Put one entry to the {@link CommitAttempt#getGlobal() global} map. Nulls are not permitted * @param entry The key and value entry * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putGlobal(Map.Entry entry) { this.global.put(entry); return this; } /** * Sets or replaces all mappings from the specified map as entries for the {@link CommitAttempt#getGlobal() global} map. Nulls are not permitted * @param entries The entries that will be added to the global map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder global(Map entries) { this.global = ImmutableMap.builder(); return putAllGlobal(entries); } /** * Put all mappings from the specified map as entries to {@link CommitAttempt#getGlobal() global} map. Nulls are not permitted * @param entries The entries that will be added to the global map * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder putAllGlobal(Map entries) { this.global.putAll(entries); return this; } /** * Adds one element to {@link CommitAttempt#getUnchanged() unchanged} list. * @param element A unchanged element * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addUnchanged(Key element) { this.unchanged.add(element); return this; } /** * Adds elements to {@link CommitAttempt#getUnchanged() unchanged} list. * @param elements An array of unchanged elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addUnchanged(Key... elements) { this.unchanged.add(elements); return this; } /** * Sets or replaces all elements for {@link CommitAttempt#getUnchanged() unchanged} list. * @param elements An iterable of unchanged elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder unchanged(Iterable elements) { this.unchanged = ImmutableList.builder(); return addAllUnchanged(elements); } /** * Adds elements to {@link CommitAttempt#getUnchanged() unchanged} list. * @param elements An iterable of unchanged elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addAllUnchanged(Iterable elements) { this.unchanged.addAll(elements); return this; } /** * Adds one element to {@link CommitAttempt#getDeletes() deletes} list. * @param element A deletes element * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addDeletes(Key element) { this.deletes.add(element); return this; } /** * Adds elements to {@link CommitAttempt#getDeletes() deletes} list. * @param elements An array of deletes elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addDeletes(Key... elements) { this.deletes.add(elements); return this; } /** * Sets or replaces all elements for {@link CommitAttempt#getDeletes() deletes} list. * @param elements An iterable of deletes elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder deletes(Iterable elements) { this.deletes = ImmutableList.builder(); return addAllDeletes(elements); } /** * Adds elements to {@link CommitAttempt#getDeletes() deletes} list. * @param elements An iterable of deletes elements * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder addAllDeletes(Iterable elements) { this.deletes.addAll(elements); return this; } /** * Initializes the value for the {@link CommitAttempt#getCommitMetaSerialized() commitMetaSerialized} attribute. * @param commitMetaSerialized The value for commitMetaSerialized * @return {@code this} builder for use in a chained invocation */ @CanIgnoreReturnValue public final Builder commitMetaSerialized(ByteString commitMetaSerialized) { this.commitMetaSerialized = Objects.requireNonNull(commitMetaSerialized, "commitMetaSerialized"); initBits &= ~INIT_BIT_COMMIT_META_SERIALIZED; return this; } /** * Builds a new {@link ImmutableCommitAttempt ImmutableCommitAttempt}. * @return An immutable instance of CommitAttempt * @throws java.lang.IllegalStateException if any required attributes are missing */ public ImmutableCommitAttempt build() { if (initBits != 0) { throw new IllegalStateException(formatRequiredAttributesMessage()); } return new ImmutableCommitAttempt(this); } private String formatRequiredAttributesMessage() { List attributes = new ArrayList<>(); if ((initBits & INIT_BIT_COMMIT_TO_BRANCH) != 0) attributes.add("commitToBranch"); if ((initBits & INIT_BIT_COMMIT_META_SERIALIZED) != 0) attributes.add("commitMetaSerialized"); return "Cannot build CommitAttempt, some of required attributes are not set " + attributes; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy