/* * Copyright 2015 Shashank Tulsyan. * * 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 neembuu.rus; import java.io.IOException; import neembuu.rus.type.TypeImplementor; import neembuu.rus.type.TypeHandlerProvider; import java.lang.reflect.Proxy; import java.nio.ByteBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import neembuu.rus.type.DefaultTypeHandlerProvider; /** * * @author Shashank */ public final class Rusila { private TypeHandlerProvider thp = new DefaultTypeHandlerProvider(); private Rus r;private boolean cache; private Rusila() {} public static Rus create(Object base){ if(base instanceof Path){ return new RusImpl((Path)base); }if(base instanceof Class){ return ClassRus.I((Class)base); }if(base instanceof Map){ return new MapRus((Map)base,null); } throw new UnsupportedOperationException("Cannot extract rus out of "+base); } public Rusila r(Rus s){ this.r = s; return this; } public Rusila thp(TypeHandlerProvider thp){ this.thp = thp; return this; } public TypeHandlerProvider thp(){ return thp; } public static Rusila newInstance(){ return new Rusila(); } public Rusila cache(boolean cache){ this.cache = cache; return this; } public static <E> SyncMap<E> s(Rus r,Class<E> template){ return new SyncedMapImpl(r,template); } public <E> E I(Class<E>interfaceDefinition){ if(!interfaceDefinition.isInterface()){ throw new IllegalStateException("Only interfaces supported " + interfaceDefinition+ r.toString()); } return (E)Proxy.newProxyInstance(Rusila.class.getClassLoader(), new Class[]{interfaceDefinition}, new TypeImplementor(r,thp)); } public static <E> E I(Rus r,Class<E>interfaceDefinition){ return I(r, interfaceDefinition, new DefaultTypeHandlerProvider()); } public static <E> E put(Rus r,Class<E>interfaceDefinition,E value){ Copier.overwrite(r, interfaceDefinition, value, new DefaultTypeHandlerProvider(),null); E e = I(r, interfaceDefinition); return e; } public static <E> E cast(Map m, Class<E>interfaceDefinition){ return I(new MapRus(m, null), interfaceDefinition); } public static void copy(Rus src, Rus dest,Class interfaceDefinition){ Copier.copy(src, dest, interfaceDefinition); } public static <E> E I(Rus r,Class<E>interfaceDefinition,TypeHandlerProvider thp){ return I(r, interfaceDefinition, thp, true); } public static <E> E I(Rus r,Class<E>interfaceDefinition,TypeHandlerProvider thp,boolean cachingEnabled){ if(!interfaceDefinition.isInterface()){ throw new IllegalStateException("Only interfaces supported " + interfaceDefinition); } if(r instanceof MapRus){cachingEnabled = false;} return (E)Proxy.newProxyInstance(Rusila.class.getClassLoader(), new Class[]{interfaceDefinition}, new TypeImplementor(r,thp,cachingEnabled)); } public static Map<String,V> getMap(Rus r){ HashMap<String,V> hm = new HashMap(); try{ Path p = ((RusImpl)r).p; DirectoryStream<Path> ds = Files.newDirectoryStream(p); for(Path pth : ds){ if(Files.isDirectory(pth))continue; String n = pth.getFileName().toString(); hm.put(n, get(r, n)); } }catch(Exception a){ a.printStackTrace(); } return hm; } public static V[] getArray(Rus r){ List<V> l = getList(r); return l.toArray(new V[l.size()]); } public static RIterable i(final Rus r,final DefaultValue dv,final TypeHandlerProvider thp){ return new RIterable(r, dv, thp); } public static List<V> getList(Rus r){ List<V> l = new LinkedList<>(); try{ Path p = ((RusImpl)r).p; DirectoryStream<Path> ds = Files.newDirectoryStream(p); for(Path pth : ds){ if(Files.isDirectory(pth))continue; String n = pth.getFileName().toString(); l.add(get(r, n)); } }catch(Exception a){ a.printStackTrace(); } return Collections.unmodifiableList(l); } public static V get(Rus r,String n){ return get(r, n, -1); //4*1024 } public static V get(Rus r,String n, int maxDataSize){ try{ return new VImpl(getVStr(r, n, maxDataSize)); }catch(java.nio.file.NoSuchFileException nsfe){ // ignore }catch(Exception a){ a.printStackTrace(); } return new VImpl(null); } public static V v(Object o){ return new VObj(o); } private static String getVStr(Rus r,String n, int maxDataSize)throws IOException{ String v; if(r instanceof ClassRus){ return ((ClassRus)r).v(n); }else { SeekableByteChannel dp = r.p(n, StandardOpenOption.READ,StandardOpenOption.CREATE); if(maxDataSize < 0) { v = getVStrF(dp); }else{ ByteBuffer bb=ByteBuffer.allocate(Math.min((int)dp.size(),maxDataSize)); dp.read(bb); v = new String(bb.array(),Charset.forName("UTF-8")); } try{dp.close();}catch(Exception a){a.printStackTrace();} } return v; } private static String getVStrF(SeekableByteChannel sbc)throws IOException{ StringBuilder sb = new StringBuilder(); ByteBuffer bf = ByteBuffer.allocate(4*1024); int i = 0; while ((i = sbc.read(bf)) > 0) { bf.flip(); sb.append(Charset.forName("UTF-8").decode(bf)); bf.clear(); } return sb.toString(); } public static void set(Rus r,String n,V v)throws Exception{ SeekableByteChannel dp = r.p( n, StandardOpenOption.WRITE,StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); dp.write(ByteBuffer.wrap(v.raw())); try{dp.close();}catch(Exception a){a.printStackTrace();} } public static void set(Rus r,String n,Object v)throws Exception{ SeekableByteChannel dp = r.p( n, StandardOpenOption.WRITE,StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING); ByteBuffer bb; if(v instanceof Integer || v instanceof Long || v instanceof Double || v instanceof Float || v instanceof Boolean || v instanceof Character){ // explicitly specifying charset to avoid localization bb=ByteBuffer.wrap(v.toString().getBytes(Charset.forName("UTF-8"))); }else if(v instanceof String){ bb=ByteBuffer.wrap(((String)v).getBytes(Charset.forName("UTF-8"))); }else { bb=SeekableByteChannel_wrap.toByteBuffer(v); } dp.write(bb); try{dp.close();}catch(Exception a){a.printStackTrace();} } public static boolean isWhiteList(Class x){ return checkContains(x, whiteList); } public static boolean isWhiteListAr(Class x){ return checkContains(x, whiteListAr); } private static boolean checkContains(Class x, Class[]s){ if(x==null)return false; for (Class cz : s) { if(cz == x || cz.equals(x) || x.isAssignableFrom(cz) ){ return true; } } return false; } static final Class[] whiteList = new Class[]{int.class,long.class,double.class, float.class,char.class,boolean.class,String.class}; static final Class[] whiteListAr = new Class[]{int[].class,long[].class,double[].class, float[].class,char[].class,boolean[].class,String[].class}; }