blob: d4bf5b58b6ce391e5d931548c06dd49c90034086 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.tamaya.metamodel;
import org.apache.tamaya.metamodel.spi.ContextInitializer;
import org.apache.tamaya.spi.ServiceContextManager;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Class managing a configuration system's meta-context. This
* context is used by the configuration system to evaluate the
* right properties, e.g. by defining the current stage or labels
* that apply to the current configuration.
*/
public final class MetaContext {
private static final Logger LOG = Logger.getLogger(MetaContext.class.getName());
private static final MetaContext INSTANCE = new MetaContext();
private final Map<String,Object> properties = new ConcurrentHashMap<>();
/** The unique id of this context. */
public MetaContext(){
setStringProperty("_id", UUID.randomUUID().toString());
initialize();
}
/**
* Get the current metacontext.
* @return the meta-context, never null.
*/
public static MetaContext getInstance() {
return INSTANCE;
}
/**
* Get the context's id.
* @return the context's id
*/
public String getId() {
return getStringProperty("_id").orElse("N/A");
}
/**
* Reads and applies the {@link ContextInitializer}s using the default classloader..
*/
public void initialize(){
initialize(ServiceContextManager.getDefaultClassLoader());
}
/**
* Reads and applies the {@link ContextInitializer}s for the given class loader.
* @param classLoader the target classloader, never null.
*/
public void initialize(ClassLoader classLoader){
for(ContextInitializer initializer: ServiceContextManager.getServiceContext(classLoader)
.getServices(ContextInitializer.class)){
try{
initializer.initializeContext(this);
}catch(Exception e){
LOG.log(Level.WARNING, "ContextInitializer failed: " + initializer.getClass().getName(), e);
}
}
}
/**
* Combine this context with the other contexts given.
* @param baseContext the base context with which the other contexts will be merged
* @param contexts the context to merge with this context.
* @return the newly created Context.
*/
public static MetaContext combineWith(MetaContext baseContext, MetaContext... contexts) {
MetaContext newContext = new MetaContext();
newContext.properties.putAll(baseContext.properties);
for(MetaContext ctx:contexts) {
newContext.properties.putAll(ctx.properties);
}
return newContext;
}
/**
* Access the given context property.
* @param key the key, not null
* @return the createValue, or null.
*/
public Optional<String> getStringProperty(String key){
return getProperty(key, String.class);
}
/**
* Access the given context property.
* @param key the key, not null
* @return the createValue, or null.
*/
public Optional<Boolean> getBooleanProperty(String key){
return getProperty(key, Boolean.class);
}
/**
* Access the given context property.
* @param key the key, not null
* @return the createValue, or null.
*/
public Optional<Number> getNumberProperty(String key){
return getProperty(key, Number.class);
}
/**
* Access the given context property.
* @param key the key, not null
* @param type the property type, not null.
* @return the createValue, or null.
*/
public <T> Optional<T> getProperty(String key, Class<T> type){
T value = (T)this.properties.get(key);
return Optional.ofNullable(value);
}
/**
* Sets the given context property.
* @param key the key, not null.
* @param value the createValue, not null.
* @return the previous createValue, or null.
*/
public String setStringProperty(String key, String value){
return setProperty(key, String.class, value);
}
/**
* Sets the given context property.
* @param key the key, not null.
* @param value the createValue, not null.
* @return the previous createValue, or null.
*/
public Boolean setBooleanProperty(String key, Boolean value){
return setProperty(key, Boolean.class, value);
}
/**
* Sets the given context property.
* @param key the key, not null.
* @param value the createValue, not null.
* @return the previous createValue, or null.
*/
public Number setNumberProperty(String key, Number value){
return setProperty(key, Number.class, value);
}
/**
* Sets the given context property.
* @param key the key, not null.
* @param value the createValue, not null.
* @param type the property type, not null.
* @param <T> the type
* @return the previous createValue, or null.
*/
public <T> T setProperty(String key, Class<T> type, T value){
T previous = (T)this.properties.put(key, Objects.requireNonNull(value));
if(previous!=null){
return previous;
}
return null;
}
/**
* Sets the given property unless there is already a createValue defined.
* @param key the key, not null.
* @param value the createValue, not null.
* @param type the property type, not null.
* @param <T> the type
* @return the value
*/
public <T> T setPropertyIfAbsent(String key, Class<T> type, T value){
T prev = (T)this.properties.get(key);
if(prev==null){
this.properties.put(key, value);
return prev;
}
return null;
}
/**
* Checks if all the given properties are present.
* @param keys the keys to check, not null.
* @return true, if all the given keys are existing.
*/
public boolean checkPropertiesArePresent(String... keys){
for(String key:keys) {
if (getProperty(key, null) == null) {
return false;
}
}
return true;
}
/**
* Access all the current context properties.
* @return the properties, never null.
*/
public Map<String,Object> getProperties(){
return Collections.unmodifiableMap(properties);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof MetaContext)) {
return false;
}
MetaContext context = (MetaContext) o;
return getProperties().equals(context.getProperties());
}
@Override
public int hashCode() {
return getProperties().hashCode();
}
@Override
public String toString() {
return "MetaContext{" +
"id=" + getId() +
", properties=" + properties +
'}';
}
}