このエントリーをはてなブックマークに追加

各種コレクションを、MapConstraint対応にします。 内部でForwardingを使っています。

@Override public V put(K key, V value) {
constraint.checkKeyValue(key, value);
return delegate.put(key, value);
}

マップとかに、値をputした際にエラーが出るようにできます。

値を入れた際にエラーを出したほうが、後で問題を発見するより楽なことがあります。

constrainedMap

MapをMapConstrainにします。

その他にも、BiMap,ListMultiMap,MultiMap,SetMultiMap,SortedSetMultiMap用のメソッドがあります。

notNull()

キーと値がnullの場合、 NullPointerExceptionが発生するconstrainedMapを返します。

キーは、英文字で始まって途中は数字と_も可能にする場合、そうでない場合は、IllegalArgumentExceptionを発生させます。

public class ValidAttributeMapConstraint implements MapConstraint<String,String>{
    private ValidAttributeMapConstraint(){}
    private static ValidAttributeMapConstraint validAttributeMapConstraint;
    public static ValidAttributeMapConstraint getValidAttributeMapConstraint(){
        if(validAttributeMapConstraint==null){
            validAttributeMapConstraint=new ValidAttributeMapConstraint();
        }
        return validAttributeMapConstraint;
    }

    public final static CharMatcher AZ=CharMatcher.inRange('A', 'Z').or(CharMatcher.inRange('a', 'z'));

    public final static CharMatcher IDENTIFIER_CHAR = CharMatcher.is('_')
            .or(AZ)
            .or(CharMatcher.inRange('0', '9'))
            .precomputed();


    @Override
    public void checkKeyValue(String key, String value) {
        if(!getValidAttributePredicate().apply(key)){
            throw new IllegalArgumentException("invalid key:"+key);
        }
    }

    public ValidAttributePredicate getValidAttributePredicate(){
        return ValidAttributePredicate.INSTANCE;
    }
    public enum ValidAttributePredicate implements Predicate<String>{
        INSTANCE;
        @Override
        public boolean apply(String input) {
            if(Strings.isNullOrEmpty(input)){
                return false;
            }

            if(!AZ.matches(input.charAt(0))){
                return false;
            }

            return IDENTIFIER_CHAR.matchesAllOf(input);
        }

    }

}