Java tutorial
/** * Copyright 2014 Jordan Zimmerman * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License 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 io.soabase.core.features.attributes; import com.google.common.base.Function; import com.google.common.base.Objects; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import io.soabase.core.listening.Listenable; import io.soabase.core.listening.ListenerContainer; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; public class StandardAttributesContainer { public static final String DEFAULT_SCOPE = ""; private final Map<String, Object> overrides = Maps.newConcurrentMap(); private final Map<AttributeKey, Object> attributes = Maps.newConcurrentMap(); private final ListenerContainer<SoaDynamicAttributeListener> listenable = new ListenerContainer<>(); private final List<String> scopes; private final AtomicBoolean firstTime = new AtomicBoolean(true); public StandardAttributesContainer(List<String> scopes) { scopes = Preconditions.checkNotNull(scopes, "scopes cannot be null"); ImmutableList.Builder<String> builder = ImmutableList.builder(); builder.addAll(scopes); builder.add(DEFAULT_SCOPE); this.scopes = builder.build(); } public interface Updater { public void put(String key, String scope, Object value); public void commit(); } public Updater newUpdater() { final Set<AttributeKey> deletingKeys = Sets.newHashSet(attributes.keySet()); final boolean notifyListeners = firstTime.compareAndSet(true, false); return new Updater() { @Override public void put(final String key, final String scope, Object value) { AttributeKey attributeKey = new AttributeKey(key, scope); deletingKeys.remove(attributeKey); final boolean isNew = !attributes.containsKey(attributeKey); if (isNew || !Objects.equal(value, attributes.get(attributeKey))) { attributes.put(attributeKey, value); Function<SoaDynamicAttributeListener, Void> notify = new Function<SoaDynamicAttributeListener, Void>() { @Override public Void apply(SoaDynamicAttributeListener listener) { if (isNew) { listener.attributeAdded(key, scope); } else { listener.attributeChanged(key, scope); } return null; } }; if (notifyListeners) { listenable.forEach(notify); } } } @Override public void commit() { for (final AttributeKey attributeKey : deletingKeys) { attributes.remove(attributeKey); if (notifyListeners) { Function<SoaDynamicAttributeListener, Void> notify = new Function<SoaDynamicAttributeListener, Void>() { @Override public Void apply(SoaDynamicAttributeListener listener) { listener.attributeRemoved(attributeKey.getKey(), attributeKey.getScope()); return null; } }; listenable.forEach(notify); } } } }; } public String getAttribute(String key, String defaultValue) { Object value = overrides.get(key); if (value == null) { value = System.getProperty(key, null); if (value == null) { value = getValue(key); } } return (value != null) ? value.toString() : defaultValue; } public boolean getAttributeBoolean(String key, boolean defaultValue) { Number value = getOverrideNumber(key); if (value != null) { return value.intValue() != 0; } return to(getValue(key), defaultValue ? 1 : 0).intValue() != 0; } public int getAttributeInt(String key, int defaultValue) { Number value = getOverrideNumber(key); if (value != null) { return value.intValue(); } return to(getValue(key), defaultValue).intValue(); } public long getAttributeLong(String key, long defaultValue) { Number value = getOverrideNumber(key); if (value != null) { return value.longValue(); } return to(getValue(key), defaultValue).longValue(); } public void temporaryOverride(String key, boolean value) { overrides.put(key, value); } public void temporaryOverride(String key, int value) { overrides.put(key, value); } public void temporaryOverride(String key, long value) { overrides.put(key, value); } public void temporaryOverride(String key, String value) { overrides.put(key, value); } public boolean removeOverride(String key) { return overrides.remove(key) != null; } public Collection<String> getKeys() { return overrides.keySet(); } public boolean hasKey(AttributeKey key) { return attributes.containsKey(key); } public Map<AttributeKey, Object> getAll() { return Maps.newHashMap(attributes); } public Listenable<SoaDynamicAttributeListener> getListenable() { return listenable; } private Object getValue(String key) { for (String scope : scopes) { Object value = attributes.get(new AttributeKey(key, scope)); if (value != null) { return value; } } return null; } private Number getOverrideNumber(String key) { Object value = overrides.get(key); if (value == null) { value = System.getProperty(key, null); } return to(value, null); } private static Number to(Object value, Number defaultValue) { if (value == null) { return defaultValue; } if (value instanceof Number) { return (Number) value; } return Long.parseLong(String.valueOf(value)); } }