private static ShapeId buildShapeId(String absoluteShapeId) {
            int namespacePosition = absoluteShapeId.indexOf('#');
            if (namespacePosition <= 0 || namespacePosition == absoluteShapeId.length() - 1) {
                throw new ShapeIdSyntaxException("Invalid shape ID: " + absoluteShapeId);
            }

            String namespace = absoluteShapeId.substring(0, namespacePosition);
            String name;
            String memberName = null;

            int memberPosition = absoluteShapeId.indexOf('$');
            if (memberPosition == -1) {
                name = absoluteShapeId.substring(namespacePosition + 1);
            } else if (memberPosition < namespacePosition) {
                throw new ShapeIdSyntaxException("Invalid shape ID: " + absoluteShapeId);
            } else {
                name = absoluteShapeId.substring(namespacePosition + 1, memberPosition);
                memberName = absoluteShapeId.substring(memberPosition + 1);
            }

            validateParts(absoluteShapeId, namespace, name, memberName);
            return new ShapeId(absoluteShapeId, namespace, name, memberName);
        }
A least-recently used flyweight factory that creates shape IDs.

<p>Prelude IDs are stored separately from non-prelude IDs because we can make a reasonable estimate about the
size of the prelude and stop caching IDs when that size is exceeded. Prelude shapes are stored in a
ConcurrentHashMap with a bounded size. Once the size exceeds 500, then items are no longer stored in the cache.
Non-prelude shapes are stored in a bounded, synchronized LRU cache based on {@link LinkedHashMap}.
smithy-model/src/main/java/software/amazon/smithy/model/shapes/ShapeId.java