001/* 002 * Copyright 2015-2018 Transmogrify LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.pyranid; 017 018import javax.annotation.Nonnull; 019import javax.annotation.concurrent.Immutable; 020import javax.annotation.concurrent.NotThreadSafe; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Map; 024import java.util.Objects; 025import java.util.Optional; 026 027import static java.lang.String.format; 028import static java.util.Objects.requireNonNull; 029 030/** 031 * Application-specific metadata associated with a SQL statement. 032 * <p> 033 * This is used in conjunction with {@link StatementLog} - for example, you might want to mark a query as "hot", or should not be logged, or ... 034 * 035 * @author <a href="http://revetkn.com">Mark Allen</a> 036 * @since 1.0.11 037 */ 038@Immutable 039public class StatementMetadata { 040 @Nonnull 041 private final Map<String, Object> metadata; 042 043 public StatementMetadata() { 044 this(new Builder()); 045 } 046 047 private StatementMetadata(@Nonnull Builder builder) { 048 requireNonNull(builder); 049 this.metadata = Collections.unmodifiableMap(new HashMap<>(builder.getMetadata())); 050 } 051 052 @Nonnull 053 public static StatementMetadata with(@Nonnull String key, @Nonnull Object value) { 054 requireNonNull(key); 055 requireNonNull(value); 056 return new Builder().add(key, value).build(); 057 } 058 059 @Nonnull 060 public Optional<Object> get(@Nonnull String key) { 061 requireNonNull(key); 062 return Optional.ofNullable(getMetadata().get(key)); 063 } 064 065 @Nonnull 066 public Map<String, Object> asMap() { 067 return getMetadata(); 068 } 069 070 @Override 071 public String toString() { 072 return format("%s{metadata=%s}", getClass().getSimpleName(), getMetadata()); 073 } 074 075 @Override 076 public boolean equals(Object object) { 077 if (this == object) 078 return true; 079 080 if (!(object instanceof StatementMetadata)) 081 return false; 082 083 StatementMetadata statementMetadata = (StatementMetadata) object; 084 085 return Objects.equals(getMetadata(), statementMetadata.getMetadata()); 086 } 087 088 @Override 089 public int hashCode() { 090 return Objects.hash(getMetadata()); 091 } 092 093 @Nonnull 094 private Map<String, Object> getMetadata() { 095 return metadata; 096 } 097 098 @NotThreadSafe 099 public static class Builder { 100 @Nonnull 101 private final Map<String, Object> metadata; 102 103 public Builder() { 104 this.metadata = new HashMap<>(); 105 } 106 107 public Builder add(@Nonnull String key, @Nonnull Object value) { 108 requireNonNull(key); 109 requireNonNull(value); 110 getMetadata().put(key, value); 111 return this; 112 } 113 114 public Builder remove(@Nonnull String key) { 115 requireNonNull(key); 116 getMetadata().remove(key); 117 return this; 118 } 119 120 @Nonnull 121 public StatementMetadata build() { 122 return new StatementMetadata(this); 123 } 124 125 @Nonnull 126 private Map<String, Object> getMetadata() { 127 return metadata; 128 } 129 } 130}