+ System.err.println("remote: " + (tsServer / 1000) % 1000 + " ("
+ + tsServer + ")");
+ System.err.println("previous: " + (tsOriginal / 1000) % 1000 + " ("
+ + tsOriginal + ")");
+ System.err.println("local changes: " + localChanges);
+ System.err.println("server changes: " + serverChanges);
+ System.err.println("choosen action: " + action);
+
+ if (action != null) {
+ s.sendCommand(Command.SELECT, name);
+ if (tsServer != StringUtils.toTime(s.receiveLine())) {
+ System.err.println("DEBUG: it changed. retry.");
+ s.sendCommand(Command.SELECT);
+ s.close();
+ return sync(force);
+ }
+
+ switch (action) {
+ case GET_CARD:
+ s.sendCommand(Command.GET_CARD);
+ List<String> data = s.receiveBlock();
+ setLastModified(data.remove(0));
+ Card server = new Card(Vcard21Parser.parseContact(data));
+ local.replaceListContent(server);
+
+ if (local.isDirty())
+ local.save();
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ break;
+ case POST_CARD:
+ s.sendCommand(Command.POST_CARD);
+ s.sendBlock(Vcard21Parser.toStrings(local));
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ setLastModified(s.receiveLine());
+ break;
+ case PUT_CARD: {
+ List<Contact> added = new LinkedList<Contact>();
+ List<Contact> removed = new LinkedList<Contact>();
+ List<Contact> from = new LinkedList<Contact>();
+ List<Contact> to = new LinkedList<Contact>();
+ original.compare(local, added, removed, from, to);
+
+ s.sendCommand(Command.PUT_CARD);
+
+ for (Contact c : removed) {
+ s.sendCommand(Command.DELETE_CONTACT, c.getId());
+ }
+ for (Contact c : added) {
+ s.sendCommand(Command.POST_CONTACT, c.getId());
+ s.sendBlock(Vcard21Parser.toStrings(c, -1));
+ }
+ if (from.size() > 0) {
+ for (int index = 0; index < from.size(); index++) {
+ Contact f = from.get(index);
+ Contact t = to.get(index);
+
+ List<Data> subadded = new LinkedList<Data>();
+ List<Data> subremoved = new LinkedList<Data>();
+ f.compare(t, subadded, subremoved, subremoved,
+ subadded);
+ s.sendCommand(Command.PUT_CONTACT, name);
+ for (Data d : subremoved) {
+ s.sendCommand(Command.DELETE_DATA,
+ d.getContentState());
+ }
+ for (Data d : subadded) {
+ s.sendCommand(Command.POST_DATA,
+ d.getContentState());
+ s.sendBlock(Vcard21Parser.toStrings(d));
+ }
+ }
+ }
+
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ s.sendCommand(Command.PUT_CARD);
+ setLastModified(s.receiveLine());
+
+ break;
+ }
+ case HASH_CONTACT: {
+ s.sendCommand(Command.PUT_CARD);
+
+ s.sendCommand(Command.LIST_CONTACT);
+ Map<String, String> remote = new HashMap<String, String>();
+ for (String line : s.receiveBlock()) {
+ int indexSp = line.indexOf(" ");
+ String hash = line.substring(0, indexSp);
+ String uid = line.substring(indexSp + 1);
+
+ remote.put(uid, hash);
+ }
+
+ List<Contact> deleted = new LinkedList<Contact>();
+ List<Contact> changed = new LinkedList<Contact>();
+ List<String> added = new LinkedList<String>();
+
+ for (Contact c : local) {
+ String hash = remote.get(c.getId());
+ if (hash == null) {
+ deleted.add(c);
+ } else if (!hash.equals(c.getContentState())) {
+ changed.add(c);
+ }
+ }
+
+ for (String uid : remote.keySet()) {
+ if (local.getById(uid) == null)
+ added.add(uid);
+ }
+
+ // process:
+
+ for (Contact c : deleted) {
+ c.delete();
+ }
+
+ for (String uid : added) {
+ s.sendCommand(Command.GET_CONTACT, uid);
+ for (Contact cc : Vcard21Parser.parseContact(s
+ .receiveBlock())) {
+ local.add(cc);
+ }
+ }
+
+ for (Contact c : changed) {
+ c.delete();
+ s.sendCommand(Command.GET_CONTACT, c.getId());
+ for (Contact cc : Vcard21Parser.parseContact(s
+ .receiveBlock())) {
+ local.add(cc);
+ }
+ }
+
+ local.save();
+ local.saveAs(getCache(cacheDirOrig), Format.VCard21);
+ s.sendCommand(Command.PUT_CARD);
+ setLastModified(s.receiveLine());
+ break;
+ }
+ default:
+ // TODO
+ throw new IOException(action
+ + " operation not supported yet :(");
+ }
+
+ s.sendCommand(Command.SELECT);
+ }
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return local;
+ } finally {
+ s.close();
+ }