software.amazon.smithy.model.loader.LoadOperation Maven / Gradle / Ivy
/*
* Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.smithy.model.loader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;
import software.amazon.smithy.model.FromSourceLocation;
import software.amazon.smithy.model.SourceLocation;
import software.amazon.smithy.model.node.Node;
import software.amazon.smithy.model.shapes.AbstractShapeBuilder;
import software.amazon.smithy.model.shapes.MemberShape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.ShapeType;
import software.amazon.smithy.model.shapes.ToShapeId;
import software.amazon.smithy.model.traits.Trait;
import software.amazon.smithy.model.validation.ValidationEvent;
abstract class LoadOperation implements FromSourceLocation {
interface Visitor {
void putMetadata(PutMetadata operation);
void applyTrait(ApplyTrait operation);
void defineShape(DefineShape shape);
void forwardReference(ForwardReference operation);
void event(Event operation);
void modelVersion(ModelVersion operation);
}
final Version version;
LoadOperation(Version version) {
this.version = version;
}
abstract void accept(Visitor visitor);
static final class PutMetadata extends LoadOperation {
final String key;
final Node value;
PutMetadata(Version version, String key, Node value) {
super(version);
this.key = key;
this.value = value;
}
@Override
public SourceLocation getSourceLocation() {
return value.getSourceLocation();
}
@Override
void accept(Visitor visitor) {
visitor.putMetadata(this);
}
}
static final class ApplyTrait extends LoadOperation {
final String namespace;
final ShapeId target;
final ShapeId trait;
final Node value;
final SourceLocation location;
ApplyTrait(
Version version,
SourceLocation location,
String namespace,
ShapeId target,
ShapeId trait,
Node value
) {
super(version);
this.namespace = namespace;
this.target = target;
this.trait = trait;
this.value = value;
this.location = location;
}
static ApplyTrait from(ShapeId target, Trait trait) {
return new ApplyTrait(Version.UNKNOWN, trait.getSourceLocation(), target.getNamespace(),
target, trait.toShapeId(), trait.toNode());
}
@Override
public SourceLocation getSourceLocation() {
return location;
}
@Override
void accept(Visitor visitor) {
visitor.applyTrait(this);
}
}
static final class DefineShape extends LoadOperation implements ToShapeId {
private final AbstractShapeBuilder, ?> builder;
private Set dependencies;
private Map members;
private List modifiers;
DefineShape(Version version, AbstractShapeBuilder, ?> builder) {
super(version);
if (builder.getShapeType() == ShapeType.MEMBER) {
throw new UnsupportedOperationException("Members must be added to top-level DefineShape instances");
}
this.builder = builder;
}
@Override
void accept(Visitor visitor) {
visitor.defineShape(this);
}
@Override
public ShapeId toShapeId() {
return builder.getId();
}
@Override
public SourceLocation getSourceLocation() {
return builder.getSourceLocation();
}
Set dependencies() {
return dependencies == null ? Collections.emptySet() : dependencies;
}
void addDependency(ShapeId id) {
if (dependencies == null) {
dependencies = new LinkedHashSet<>();
}
dependencies.add(id);
}
ShapeType getShapeType() {
return builder.getShapeType();
}
AbstractShapeBuilder, ?> builder() {
return builder;
}
void addMember(MemberShape.Builder member) {
if (members == null) {
members = new LinkedHashMap<>();
}
members.put(member.getId().getMember().get(), member);
}
boolean hasMember(String memberName) {
return members != null && members.containsKey(memberName);
}
Map memberBuilders() {
return members == null ? Collections.emptyMap() : members;
}
List modifiers() {
return modifiers == null ? Collections.emptyList() : modifiers;
}
void addModifier(ShapeModifier modifier) {
if (modifiers == null) {
modifiers = new ArrayList<>();
}
modifiers.add(modifier);
}
}
static final class ForwardReference extends LoadOperation {
final String namespace;
final String name;
private final BiFunction receiver;
ForwardReference(String namespace, String name, BiFunction receiver) {
super(Version.UNKNOWN);
this.namespace = namespace;
this.name = name;
this.receiver = receiver;
}
@Override
void accept(Visitor visitor) {
visitor.forwardReference(this);
}
ValidationEvent resolve(ShapeId id, ShapeType type) {
return receiver.apply(id, type);
}
}
static final class Event extends LoadOperation {
final ValidationEvent event;
Event(ValidationEvent event) {
super(Version.UNKNOWN);
this.event = event;
}
@Override
void accept(Visitor visitor) {
visitor.event(this);
}
}
static final class ModelVersion extends LoadOperation {
final SourceLocation sourceLocation;
ModelVersion(Version version, SourceLocation sourceLocation) {
super(version);
this.sourceLocation = sourceLocation;
}
@Override
void accept(Visitor visitor) {
visitor.modelVersion(this);
}
@Override
public SourceLocation getSourceLocation() {
return sourceLocation;
}
}
}