Skip to content

Commit

Permalink
Add a caching SymbolProvider
Browse files Browse the repository at this point in the history
  • Loading branch information
mtdowling committed Sep 19, 2019
1 parent 770012d commit 00476c7
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2019 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.codegen.core;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;

/**
* Caches the results of calling {@code toSymbol} and {@code toMemberName}.
*/
final class CachingSymbolProvider implements SymbolProvider {

private final SymbolProvider delegate;
private final ConcurrentMap<ShapeId, Symbol> symbolCache = new ConcurrentHashMap<>();
private final ConcurrentMap<ShapeId, String> memberCache = new ConcurrentHashMap<>();

CachingSymbolProvider(SymbolProvider delegate) {
this.delegate = delegate;
}

@Override
public Symbol toSymbol(Shape shape) {
return symbolCache.computeIfAbsent(shape.toShapeId(), id -> delegate.toSymbol(shape));
}

@Override
public String toMemberName(Shape shape) {
return memberCache.computeIfAbsent(shape.toShapeId(), id -> delegate.toMemberName(shape));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,25 @@ public interface SymbolProvider {
default String toMemberName(Shape shape) {
return shape.getId().getMember().orElseGet(() -> StringUtils.uncapitalize(shape.getId().getName()));
}

/**
* Decorates a {@code SymbolProvider} with a cache and returns the
* decorated {@code SymbolProvider}.
*
* <p>The results of calling {@code toSymbol} and {@code toMemberName}
* on {@code delegate} are cached using a thread-safe cache.
*
* <pre>
* {@code
* SymbolProvider delegate = createComplexProvider(myModel);
* SymbolProvider cachingProvider = SymbolProvider.cache(delegate);
* }
* </pre>
*
* @param delegate Symbol provider to wrap and cache its results.
* @return Returns the wrapped SymbolProvider.
*/
static SymbolProvider cache(SymbolProvider delegate) {
return new CachingSymbolProvider(delegate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package software.amazon.smithy.codegen.core;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.equalTo;

import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import software.amazon.smithy.model.shapes.MemberShape;
import software.amazon.smithy.model.shapes.Shape;
import software.amazon.smithy.model.shapes.ShapeId;
import software.amazon.smithy.model.shapes.StringShape;

public class CachingSymbolProviderTest {
@Test
public void cachesResults() {
List<ShapeId> calls = new ArrayList<>();

SymbolProvider delegate = shape -> {
calls.add(shape.getId());
return Symbol.builder().name(shape.getId().getName()).build();
};

SymbolProvider cache = SymbolProvider.cache(delegate);

Shape a = StringShape.builder().id("foo.baz#A").build();
Shape b = StringShape.builder().id("foo.baz#B").build();
Shape c = MemberShape.builder().id("foo.baz#C$c").target(a).build();

assertThat(cache.toSymbol(a).getName(), equalTo("A"));
assertThat(cache.toSymbol(b).getName(), equalTo("B"));
assertThat(cache.toSymbol(c).getName(), equalTo("C"));
assertThat(cache.toSymbol(a).getName(), equalTo("A"));
assertThat(cache.toSymbol(b).getName(), equalTo("B"));
assertThat(cache.toSymbol(c).getName(), equalTo("C"));
assertThat(cache.toMemberName(c), equalTo("c"));

assertThat(calls, containsInAnyOrder(a.getId(), b.getId(), c.getId()));
}
}

0 comments on commit 00476c7

Please sign in to comment.