Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package jnetention; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import java.io.File; import java.io.IOException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Collections; import java.util.List; import java.util.Map; import javafx.application.Platform; import jnetention.p2p.Listener; import jnetention.p2p.Network; import org.apache.commons.math3.stat.Frequency; import org.mapdb.BTreeMap; import org.mapdb.DB; import org.mapdb.DBMaker; /** * Unifies DB & P2P features */ public class Core extends EventEmitter { private final static String Session_MYSELF = "myself"; private final BTreeMap<Object, Object> session; public Network net; public static class SaveEvent { public final NObject object; public SaveEvent(NObject object) { this.object = object; } } public static class NetworkUpdateEvent { } //DATABASE public final BTreeMap<String, NObject> data; public final DB db; private NObject myself; /** in-memory Database */ public Core() { this(DBMaker.newMemoryDirectDB().make()); } /** file Database */ public Core(String filePath) { this(DBMaker.newFileDB(new File(filePath)).closeOnJvmShutdown().transactionDisable() //.encryptionEnable("password") .make()); } public Core(DB db) { this.db = db; // open existing an collection (or create new) data = db.getTreeMap("objects"); session = db.getTreeMap("session"); if (session.get(Session_MYSELF) == null) { //first time user become(newUser("Anonymous " + NObject.UUID().substring(0, 4))); } // map.put(1, "one"); // map.put(2, "two"); // // map.keySet() is now [1,2] // // db.commit(); //persist changes into disk // // map.put(3, "three"); // // map.keySet() is now [1,2,3] // db.rollback(); //revert recent changes // // map.keySet() is now [1,2] // // db.close(); } public Core online(int listenPort) throws IOException, UnknownHostException, SocketException, InterruptedException { net = new Network(listenPort); net.listen("obj.", new Listener() { @Override public void handleMessage(String topic, String message) { System.err.println("recv: " + message); } }); //net.getConfiguration().setBehindFirewall(true); System.out.println("Server started listening to "); System.out.println("Accessible to outside networks at "); return this; } protected void broadcastSelf() { if (myself != null) Platform.runLater(new Runnable() { @Override public void run() { broadcast(myself); } }); } public void connect(String host, int port) throws UnknownHostException { net.connect(host, port); } /*public Core offline() { return this; }*/ public Iterable<NObject> netValues() { return Collections.EMPTY_LIST; // // //dht.storageLayer().checkTimeout(); // return Iterables.filter(Iterables.transform(dht.storageLayer().get().values(), // new Function<Data,NObject>() { // @Override public NObject apply(final Data f) { // try { // final Object o = f.object(); // if (o instanceof NObject) { // NObject n = (NObject)o; // // if (data.containsKey(n.id)) // return null; // // /*System.out.println("net value: " + f.object() + " " + f.object().getClass() + " " + data.containsKey(n.id));*/ // return n; // } // /*else { // System.out.println("p: " + o + " " + o.getClass()); // }*/ // /*else if (o instanceof String) { // Object p = dht.get(Number160.createHash((String)o)); // System.out.println("p: " + p + " " + p.getClass()); // }*/ // return null; // } catch (Exception ex) { // ex.printStackTrace(); // return null; // } // } // }), Predicates.notNull()); } public Iterable<NObject> allValues() { if (net != null) { return Iterables.concat(data.values(), netValues()); } else { return data.values(); } } public Iterable<NObject> tagged(final String tagID) { return Iterables.filter(allValues(), new Predicate<NObject>() { @Override public boolean apply(final NObject o) { return o.hasTag(tagID); } }); } public Iterable<NObject> tagged(final String tagID, final String author) { return Iterables.filter(allValues(), new Predicate<NObject>() { @Override public boolean apply(final NObject o) { if (author != null) if (!author.equals(o.author)) return false; return o.hasTag(tagID); } }); } public Iterable<NObject> tagged(final Tag t) { return tagged(t.name()); } public List<NObject> getUsers() { return Lists.newArrayList(tagged(Tag.User)); } public List<NObject> getSubjects() { //TODO list all possible subjects, not just users return getUsers(); } public List<NObject> getTags() { List<NObject> c = Lists.newArrayList(tagged(Tag.tag)); for (Tag sysTag : Tag.values()) c.add(NTag.asNObject(sysTag)); return c; } public NObject newUser(String name) { NObject n = new NObject(name); n.author = n.id; n.add(Tag.User); n.add(Tag.Human); n.add("@", new SpacePoint(40, -80)); publish(n); return n; } /** creates a new anonymous object, but doesn't publish it yet */ public NObject newAnonymousObject(String name) { NObject n = new NObject(name); return n; } /** creates a new object (with author = myself), but doesn't publish it yet */ public NObject newObject(String name) { if (myself == null) throw new RuntimeException("Unidentified; can not create new object"); NObject n = new NObject(name); n.author = myself.id; return n; } public void become(NObject user) { //System.out.println("Become: " + user); myself = user; session.put(Session_MYSELF, user.id); } public void remove(String nobjectID) { data.remove(nobjectID); } public void remove(NObject x) { remove(x.id); } /** save nobject to database */ public void save(NObject x) { NObject removed = data.put(x.id, x); index(removed, x); emit(SaveEvent.class, x); } /** batch save nobject to database */ public void save(Iterable<NObject> y) { for (NObject x : y) { NObject removed = data.put(x.id, x); index(removed, x); } emit(SaveEvent.class, null); } public void broadcast(NObject x) { broadcast(x, false); } public synchronized void broadcast(NObject x, boolean block) { if (net != null) { System.err.println("broadcasting " + x); net.send("obj0", x.toStringDetailed()); // try { // // // } // catch (IOException e) { // System.err.println("publish: " + e); // } } } /** save to database and publish in DHT */ public void publish(NObject x, boolean block) { save(x); broadcast(x, block); //TODO save to geo-index } public void publish(NObject x) { publish(x, false); } /* public int getNetID() { if (net == null) return -1; return net. } */ public NObject getMyself() { return myself; } protected void index(NObject previous, NObject o) { if (previous != null) { if (previous.isClass()) { } } if (o != null) { if ((o.isClass()) || (o.isProperty())) { for (Map.Entry<String, Object> e : o.value.entries()) { String superclass = e.getKey(); if (superclass.equals("tag")) continue; if (getTag(superclass) == null) { save(new NTag(superclass)); } } } } } public static Frequency tokenBag(String x, int minLength, int maxTokenLength) { String[] tokens = tokenize(x); Frequency f = new Frequency(); for (String t : tokens) { if (t == null) continue; if (t.length() < minLength) continue; if (t.length() > maxTokenLength) continue; t = t.toLowerCase(); f.addValue(t); } return f; } public static String[] tokenize(String value) { String v = value.replaceAll(",", " \uFFEB ").replaceAll("\\.", " \uFFED").replaceAll("\\!", " \uFFED"). //TODO alternate char replaceAll("\\?", " \uFFED") //TODO alternate char ; return v.split(" "); } public Object getTag(String tagID) { NObject tag = data.get(tagID); if (tag != null && tag.isClass()) return tag; return null; } public Iterable<NObject> getTagRoots() { return Iterables.filter(getTags(), new Predicate<NObject>() { @Override public boolean apply(NObject t) { try { NTag tag = (NTag) t; return tag.getSuperTags().isEmpty(); } catch (Exception e) { } return false; } }); } }