Make sets ordered
This commit is contained in:
parent
28faa492ba
commit
6084e16123
|
@ -597,6 +597,11 @@ in a response.
|
|||
``uniqueItems`` trait
|
||||
---------------------
|
||||
|
||||
.. warning:
|
||||
|
||||
This trait has been deprecated. It may be removed in future versions. Set
|
||||
shapes should be used instead.
|
||||
|
||||
Summary
|
||||
Indicates that the items in a :ref:`list` MUST be unique.
|
||||
Trait selector
|
||||
|
|
|
@ -458,7 +458,7 @@ reference other shapes using :ref:`members <member>`.
|
|||
* - :ref:`list`
|
||||
- Ordered collection of homogeneous values
|
||||
* - :ref:`set`
|
||||
- Unordered collection of unique homogeneous values
|
||||
- Collection of unique homogeneous values
|
||||
* - :ref:`map`
|
||||
- Map data structure that maps string keys to homogeneous values
|
||||
* - :ref:`structure`
|
||||
|
@ -565,7 +565,7 @@ example is ``smithy.example#MyList$member``.
|
|||
Set
|
||||
===
|
||||
|
||||
The :dfn:`set` type represents an unordered collection of unique homogeneous
|
||||
The :dfn:`set` type represents a collection of unique homogeneous
|
||||
values. A set shape requires a single member named ``member``.
|
||||
Sets are defined in the IDL using a :ref:`set_statement <idl-set>`.
|
||||
The following example defines a set of strings:
|
||||
|
@ -618,6 +618,13 @@ SHOULD represent sets as a custom set data structure that can interpret value
|
|||
hash codes and equality, or alternatively, store the values of a set data
|
||||
structure in a list and rely on validation to ensure uniqueness.
|
||||
|
||||
.. rubric:: Set member ordering
|
||||
|
||||
Sets MUST be insertion ordered. Not all programming languages that support
|
||||
sets support ordered sets, requiring them may be overly burdensome for users,
|
||||
or conflict with language idioms. Such languages SHOULD store the values
|
||||
of sets in a list and rely on validation to ensure uniqueness.
|
||||
|
||||
|
||||
.. _map:
|
||||
|
||||
|
|
|
@ -205,7 +205,7 @@ public final class ServiceIndex implements KnowledgeIndex {
|
|||
|
||||
AuthTrait authTrait = subject.expectTrait(AuthTrait.class);
|
||||
Map<ShapeId, Trait> result = new LinkedHashMap<>();
|
||||
for (ShapeId value : authTrait.getValues()) {
|
||||
for (ShapeId value : authTrait.getValueSet()) {
|
||||
service.findTrait(value).ifPresent(trait -> result.put(value, trait));
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -174,9 +175,11 @@ final class DefaultNodeDeserializers {
|
|||
|| targetType.equals(ArrayList.class)
|
||||
|| targetType.equals(Iterable.class)) {
|
||||
return ArrayList::new;
|
||||
} else if (targetType.equals(Set.class) || targetType.equals(HashSet.class)) {
|
||||
} else if (targetType.equals(Set.class)
|
||||
|| targetType.equals(HashSet.class)
|
||||
|| targetType.equals(LinkedHashSet.class)) {
|
||||
// Special casing for Set or HashSet.
|
||||
return HashSet::new;
|
||||
return LinkedHashSet::new;
|
||||
} else if (Collection.class.isAssignableFrom(targetType)) {
|
||||
return createSupplierFromReflection(targetType);
|
||||
}
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
|
||||
package software.amazon.smithy.model.traits;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import software.amazon.smithy.model.FromSourceLocation;
|
||||
import software.amazon.smithy.model.SourceLocation;
|
||||
import software.amazon.smithy.model.node.ArrayNode;
|
||||
|
@ -24,6 +25,7 @@ import software.amazon.smithy.model.node.Node;
|
|||
import software.amazon.smithy.model.node.StringNode;
|
||||
import software.amazon.smithy.model.shapes.ShapeId;
|
||||
import software.amazon.smithy.utils.ListUtils;
|
||||
import software.amazon.smithy.utils.SetUtils;
|
||||
|
||||
/**
|
||||
* Specifies the auth schemes supported by default for operations
|
||||
|
@ -33,26 +35,42 @@ public final class AuthTrait extends AbstractTrait {
|
|||
|
||||
public static final ShapeId ID = ShapeId.from("smithy.api#auth");
|
||||
|
||||
private final List<ShapeId> values;
|
||||
private final Set<ShapeId> values;
|
||||
|
||||
@Deprecated
|
||||
public AuthTrait(List<ShapeId> values, FromSourceLocation sourceLocation) {
|
||||
super(ID, sourceLocation);
|
||||
this.values = ListUtils.copyOf(values);
|
||||
this.values = SetUtils.orderedCopyOf(values);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public AuthTrait(List<ShapeId> values) {
|
||||
this(values, SourceLocation.NONE);
|
||||
}
|
||||
|
||||
public AuthTrait(Set<ShapeId> values, FromSourceLocation sourceLocation) {
|
||||
super(ID, sourceLocation);
|
||||
this.values = SetUtils.orderedCopyOf(values);
|
||||
}
|
||||
|
||||
public AuthTrait(Set<ShapeId> values) {
|
||||
this(values, SourceLocation.NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the auth scheme trait values.
|
||||
*
|
||||
* @return Returns the supported auth schemes.
|
||||
*/
|
||||
public List<ShapeId> getValues() {
|
||||
public Set<ShapeId> getValueSet() {
|
||||
return values;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public List<ShapeId> getValues() {
|
||||
return ListUtils.copyOf(values);
|
||||
}
|
||||
|
||||
public static final class Provider extends AbstractTrait.Provider {
|
||||
public Provider() {
|
||||
super(ID);
|
||||
|
@ -60,7 +78,7 @@ public final class AuthTrait extends AbstractTrait {
|
|||
|
||||
@Override
|
||||
public Trait createTrait(ShapeId target, Node value) {
|
||||
List<ShapeId> values = new ArrayList<>();
|
||||
Set<ShapeId> values = new LinkedHashSet<>();
|
||||
for (StringNode node : value.expectArrayNode().getElementsAs(StringNode.class)) {
|
||||
values.add(node.expectShapeId());
|
||||
}
|
||||
|
@ -70,7 +88,7 @@ public final class AuthTrait extends AbstractTrait {
|
|||
|
||||
@Override
|
||||
protected Node createNode() {
|
||||
return getValues().stream().map(ShapeId::toString).map(Node::from)
|
||||
return getValueSet().stream().map(ShapeId::toString).map(Node::from)
|
||||
.collect(ArrayNode.collect(getSourceLocation()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
package software.amazon.smithy.model.traits;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -121,12 +121,12 @@ public final class CorsTrait extends AbstractTrait implements ToSmithyBuilder<Co
|
|||
}
|
||||
|
||||
public Builder additionalAllowedHeaders(Set<String> additionalAllowedHeaders) {
|
||||
this.additionalAllowedHeaders = new HashSet<>(Objects.requireNonNull(additionalAllowedHeaders));
|
||||
this.additionalAllowedHeaders = new LinkedHashSet<>(Objects.requireNonNull(additionalAllowedHeaders));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder additionalExposedHeaders(Set<String> additionalExposedHeaders) {
|
||||
this.additionalExposedHeaders = new HashSet<>(Objects.requireNonNull(additionalExposedHeaders));
|
||||
this.additionalExposedHeaders = new LinkedHashSet<>(Objects.requireNonNull(additionalExposedHeaders));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ import software.amazon.smithy.model.shapes.ShapeId;
|
|||
/**
|
||||
* Indicates that the members of a list must be unique.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class UniqueItemsTrait extends AnnotationTrait {
|
||||
public static final ShapeId ID = ShapeId.from("smithy.api#uniqueItems");
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ public final class AuthTraitValidator extends AbstractValidator {
|
|||
) {
|
||||
if (shape.getTrait(AuthTrait.class).isPresent()) {
|
||||
AuthTrait authTrait = shape.getTrait(AuthTrait.class).get();
|
||||
Set<ShapeId> appliedAuthTraitValue = new TreeSet<>(authTrait.getValues());
|
||||
Set<ShapeId> appliedAuthTraitValue = new TreeSet<>(authTrait.getValueSet());
|
||||
appliedAuthTraitValue.removeAll(serviceAuth);
|
||||
|
||||
if (!appliedAuthTraitValue.isEmpty()) {
|
||||
|
|
|
@ -116,8 +116,7 @@ map externalDocumentation {
|
|||
|
||||
/// Defines the list of authentication schemes supported by a service or operation.
|
||||
@trait(selector: ":is(service, operation)")
|
||||
@uniqueItems
|
||||
list auth {
|
||||
set auth {
|
||||
member: AuthTraitReference
|
||||
}
|
||||
|
||||
|
@ -502,6 +501,7 @@ structure sparse {}
|
|||
|
||||
/// Indicates that the items in a list MUST be unique.
|
||||
@trait(selector: "list")
|
||||
@deprecated(message: "The uniqueItems trait has been deprecated in favor of using sets.", since: "2.0")
|
||||
structure uniqueItems {}
|
||||
|
||||
/// Indicates that the shape is unstable and could change in the future.
|
||||
|
|
|
@ -784,7 +784,7 @@ public class NodeMapperTest {
|
|||
NodeMapper mapper = new NodeMapper();
|
||||
|
||||
Set<String> result = mapper.deserializeCollection(value, Set.class, String.class);
|
||||
assertThat(result, instanceOf(HashSet.class));
|
||||
assertThat(result, instanceOf(LinkedHashSet.class));
|
||||
assertThat(result, contains("a", "b"));
|
||||
}
|
||||
|
||||
|
@ -794,7 +794,7 @@ public class NodeMapperTest {
|
|||
NodeMapper mapper = new NodeMapper();
|
||||
|
||||
Set<String> result = mapper.deserializeCollection(value, HashSet.class, String.class);
|
||||
assertThat(result, instanceOf(HashSet.class));
|
||||
assertThat(result, instanceOf(LinkedHashSet.class));
|
||||
assertThat(result, contains("a", "b"));
|
||||
}
|
||||
|
||||
|
|
|
@ -516,7 +516,7 @@ public final class OpenApiConverter {
|
|||
// If the operation explicitly removes authentication, ensure that "security" is set to an empty
|
||||
// list as opposed to simply being unset as unset will result in the operation inheriting global
|
||||
// configuration.
|
||||
if (shape.getTrait(AuthTrait.class).map(trait -> trait.getValues().isEmpty()).orElse(false)) {
|
||||
if (shape.getTrait(AuthTrait.class).map(trait -> trait.getValueSet().isEmpty()).orElse(false)) {
|
||||
builder.security(Collections.emptyList());
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue