Java tutorial
/* * Copyright (C) 2013 Andrey Chaschev. * * 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 bear.context; import bear.session.DynamicVariable; import bear.session.Variables; import chaschev.util.Exceptions; import com.google.common.base.Function; import com.google.common.base.Functions; import com.google.common.base.Preconditions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.Map; import java.util.Properties; import java.util.concurrent.Callable; import static bear.session.Variables.getConverter; /** * @author Andrey Chaschev chaschev@gmail.com */ public abstract class AbstractContext { public static final Logger logger = LoggerFactory.getLogger(AbstractContext.class); protected VariablesLayer layer; protected AbstractContext parent; protected AppGlobalContext global; protected Properties properties = new Properties(); protected final InjectingContext<?> injectingContext; protected String name; protected AbstractContext(VariablesLayer layer) { this(layer, null); } protected AbstractContext(AbstractContext parentContext, String name) { this(new VariablesLayer(name, parentContext.layer), parentContext); } protected AbstractContext(AppGlobalContext global, String name) { this((AbstractContext) global, name); this.global = global; if (injectingContext != null) injectingContext.global = global; } protected AbstractContext(VariablesLayer layer, AbstractContext parentContext) { this.name = layer.name; this.layer = layer; this.parent = parentContext; layer.set$(this); injectingContext = this instanceof InjectingContext ? null : new InjectingContext(this); } public <T> T varByName(String name) { return (T) var(name, Fun.UNDEFINED); } public <T> T var(Nameable<T> var) { return var(layer.getVariable(var)); } public <T> T var(DynamicVariable<T> var) { return layer.get(var); } public <T> T getAt(DynamicVariable<T> var) { return layer.get(var); } public boolean varB(DynamicVariable<Boolean> var) { return layer.get(var); } <T> T var(String varName, T _default) { return layer.get(varName, _default); } public <T> boolean isSet(Nameable<T> variable) { return layer.isSet(variable); } /** * Should be overridden to specify type. */ public AppGlobalContext getGlobal() { return global; } public <T> AbstractContext put(DynamicVariable<T> key, T value) { layer.putConst(key, value); return this; } public <T> AbstractContext put(DynamicVariable<T> key, DynamicVariable<T> value) { layer.put(key, value); return this; } public VariablesLayer put(String key, DynamicVariable value) { return layer.put(key, value); } public VariablesLayer put(DynamicVariable value) { return layer.put(value); } // public VariablesLayer put(Nameable key, boolean b) { // return layer.putB(key, b); // } public <T> T wire(T object) { DependencyInjection.nameVars(object, global == null ? (AppGlobalContext) this : global); if (injectingContext != null) { return injectingContext.wire(object); } throw new IllegalStateException(); } public void setName(String name) { this.name = name; layer.setName(name); } public String getName() { return name; } public VariablesLayer getLayer() { return layer; } public String getProperty(String s) { if (global == null) { return properties.getProperty(s); } return global.getProperty(s); } public void loadProperties(File file) { try { final FileInputStream fis = new FileInputStream(file); loadProperties(fis); } catch (IOException e) { throw Exceptions.runtime(e); } } public void loadProperties(InputStream is) throws IOException { Preconditions.checkNotNull(is); properties.load(is); loadProperties(properties); } //todo support conversion public void loadProperties(Properties prop) { this.properties = prop; final Enumeration<?> enumeration = prop.propertyNames(); while (enumeration.hasMoreElements()) { final String name = (String) enumeration.nextElement(); final Object v = prop.get(name); if (v instanceof Boolean) { final DynamicVariable<Boolean> value = Variables.newVar((Boolean) v).setName(name); layer.put(value, value); } else if (v instanceof String) { final DynamicVariable<String> value = Variables.newVar((String) v).setName(name); layer.put(value, value); } else { throw new UnsupportedOperationException("todo: implement for " + v.getClass()); } } } public Object getConstant(Object obj) { return layer.getConstant(obj); } public <T> DynamicVariable<T> getVariable(Nameable<T> name) { return layer.getVariable(name); } public <T> DynamicVariable<T> getVariable(String key) { return layer.getVariable(key); } public <T> AbstractContext putConst(Nameable<? extends T> key, T value) { layer.putConst(key, value); return this; } public <T> AbstractContext putConst(DynamicVariable<? extends T> key, T value) { layer.putConst(key, value); return this; } public AbstractContext putConst(String name, Object value) { layer.putConst(name, value); return this; } public AbstractContext convertAndPutConst(String name, String value) { return convertAndPutConst(name, value, getGlobal().variableRegistry.getType(name)); } public AbstractContext convertAndPutConst(String name, String value, Class<?> type) { Function<String, ?> converter; if (type == null) { converter = Functions.identity(); } else { converter = getConverter(type); } Preconditions.checkNotNull(converter, "converter not found for type: " + (type == null ? null : type.getSimpleName())); return putConst(name, converter.apply(value)); } public AbstractContext putConstObj(Object key, Object value) { layer.putConstObj(key, value); return this; } public AbstractContext removeConst(Nameable key) { layer.removeConst(key); return this; } public AbstractContext removeConst(String name) { layer.removeConst(name); return this; } public boolean isGlobal() { return false; //global == null } public AbstractContext setParent(AbstractContext context) { layer.fallbackVariablesLayer = context.layer; this.parent = context; if (global == null && context instanceof AppGlobalContext<?, ?>) { global = (AppGlobalContext) context; } return this; } public AbstractContext getParent() { return parent; } public boolean isDefined(DynamicVariable var) { return var.isDefined() || isSet(var); } public boolean isUndefined(DynamicVariable var) { return !isDefined(var); } public Map<Object, Object> putMap(Map<Object, Object> constantsAndVars) { return layer.putMap(constantsAndVars, true); } public <R> R withMap(Map<Object, Object> constantsAndVars, Callable<R> callable) { Map savedEntries = layer.putMap(constantsAndVars, true); try { return callable.call(); } catch (Exception e) { throw Exceptions.runtime(e); } finally { layer.putMap(savedEntries); } } @Override public String toString() { final StringBuilder sb = new StringBuilder("Context{"); sb.append("name='").append(name).append('\''); sb.append(", constants=").append(layer.constants.size()); sb.append(", vars=").append(layer.variables.size()); sb.append('}'); return sb.toString(); } }