001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.config; 005 006 import biz.hammurapi.util.Attributable; 007 008 /** 009 * Helper class to navigate context trees. Follows unix filesystem naming convention: / is a path separator, 010 * . is current element, .. is parent element, absolute path starts with / 011 * @author Pavel Vlasov 012 * @revision $Revision$ 013 */ 014 public abstract class PathNavigator implements Context { 015 016 protected Object master; 017 018 public PathNavigator(Object master) { 019 this.master=master; 020 } 021 022 protected abstract Object getParent(); 023 protected abstract Object getChild(String name); 024 025 public Object get(String name) { 026 try { 027 Object ret=lookup(name); 028 if (ret instanceof Service) { 029 ((Service) ret).start(); 030 } 031 032 if (ret instanceof Wrapper) { 033 ret = ((Wrapper) ret).getMaster(); 034 } 035 036 if (ret instanceof Service) { 037 ((Service) ret).start(); 038 } 039 040 return ret; 041 } catch (ConfigurationException e) { 042 throw new RuntimeConfigurationException(e); 043 } 044 } 045 046 private Object lookup(String name) { 047 if (name.startsWith("/")) { 048 if (getParent() instanceof Context) { 049 return ((Context) getParent()).get(name); 050 } 051 return name.equals("/") ? master : get(name.substring(1)); 052 } else if ("..".equals(name)) { 053 return getParent(); 054 } else if (name.startsWith("../")) { 055 return (getParent() instanceof Context) ? ((Context) getParent()).get(name.substring(3)) : null; 056 } 057 058 int idx=name.indexOf('/'); 059 if (idx==-1) { 060 if (name.startsWith("@") && master instanceof Attributable) { 061 return ((Attributable) master).getAttribute(name.substring(1)); 062 } 063 064 return ".".equals(name) ? master : getChild(name); 065 } 066 067 String nameElement = name.substring(0, idx); 068 Object child = ".".equals(nameElement) ? master : getChild(nameElement); 069 if (child instanceof Context) { 070 return ((Context) child).get(name.substring(idx+1)); 071 } 072 073 return null; 074 } 075 076 /** 077 * @param master Master context. 078 * @param parent Parent object. 079 * @return Instance of PathNavigator. 080 */ 081 public static Context newInstance(Context master, final Object parent) { 082 return new PathNavigator(master) { 083 084 protected Object getParent() { 085 return parent; 086 } 087 088 protected Object getChild(String name) { 089 return ((Context) master).get(name); 090 } 091 092 }; 093 } 094 095 }