Package com.onpositive.gae.baseviewer

Source Code of com.onpositive.gae.baseviewer.BaseDataFacade$Callback

package com.onpositive.gae.baseviewer;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.IControlContentAdapter;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;

import com.google.appengine.api.datastore.Blob;
import com.google.appengine.api.datastore.Category;
import com.google.appengine.api.datastore.Email;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PhoneNumber;
import com.google.appengine.api.datastore.PostalAddress;
import com.google.appengine.api.datastore.Rating;
import com.google.apphosting.api.ApiProxy;
import com.onpositive.commons.contentassist.BasicContentProposal;
import com.onpositive.commons.ui.tableeditor.Field;
import com.onpositive.commons.ui.tableeditor.Filter;
import com.onpositive.commons.ui.tableeditor.IDataCallback;
import com.onpositive.commons.ui.tableeditor.IDataFacade;
import com.onpositive.commons.ui.tableeditor.IFilterListener;
import com.onpositive.commons.ui.tableeditor.ISingleCallback;
import com.onpositive.commons.ui.tableeditor.OperationCallback;
import com.onpositive.commons.ui.tableeditor.Query;
import com.onpositive.commons.ui.tableeditor.Sort;
import com.onpositive.gae.baseviewer.ProjectMiner.FieldInfo;
import com.onpositive.gae.baseviewer.Request.ComplexFilter;
import com.onpositive.gae.baseviewer.Request.RequestPart;
import com.onpositive.gae.baseviewer.Request.State;
import com.onpositive.gae.baseviewer.requests.IComplexFacade;
import com.onpositive.gae.baseviewer.requests.IComplexQueryRequest;
import com.onpositive.gae.baseviewer.requests.ReificationRequest;
import com.onpositive.gae.baseviewer.requests.SimpleRequest;
import com.onpositive.gae.tools.GaeBridge;
import com.onpositive.gae.tools.SessionManager;
import com.onpositive.gae.tools.core.CheckLaunchJob;
import com.onpositive.gae.tools.core.DebugServerLaunchManager;
import com.onpositive.gae.tools.license.BadUserIdException;
import com.onpositive.semantic.model.realm.IRealm;
import com.onpositive.semantic.model.realm.Realm;

public class BaseDataFacade implements IDataFacade, Cloneable,
    ICommonOperations {

  private boolean skipReconnect = false;

  public boolean isSkipReconnect() {
    return skipReconnect;
  }

  public void setSkipReconnect(boolean skipReconnect) {
    this.skipReconnect = skipReconnect;
  }

  private Map children;
  private Map parents;

  protected String namespace = "";

  public String getNamespace() {
    return namespace;
  }

  public void setNamespace(String namespace) {
    this.namespace = namespace;
  }

  public Map getChildren() {
    return children;
  }

  public Map getParents() {
    return parents;
  }

  private HashMap<String, String> kindsOfChildren;
  private HashMap<String, Class> persistentFields;
  private HashMap<String, FieldInfo> embeddedFields;

  public HashMap<String, FieldInfo> getEmbeddedFields() {
    return embeddedFields;
  }

  public HashMap<String, String> getKindsOfChildren() {
    return kindsOfChildren;
  }

  static final NumberFormat format = NumberFormat.getNumberInstance();
  static {
    format.setMaximumFractionDigits(15);
  }

  static final DateFormat dt = DateFormat.getDateTimeInstance();

  protected static HashMap<Class<?>, CellEditorFactory> t = new HashMap<Class<?>, CellEditorFactory>();

  DataViewPart pm;

  public static final String ONPOSITIVE_MAGIC_SHORTENED_PROPERTIES = "ONPOSITIVE_MAGIC_SHORTENED_PROPERTIES";

  protected String kind;

  public void setKind(String kind) {
    this.kind = kind;
  }

  protected IJavaProject project;

  public void setProject(IJavaProject project) {
    this.project = project;
  }

  protected boolean completed;

  protected boolean debug;

  protected IDataCallback refreshCallback;

  protected ISingleCallback singleCall;

  protected long bytesReaded;

  public void dispose() {
    if (currentJob != null) {
      currentJob.cancel();
    }
  }

  private final class FindChildrenJob extends Job {
    private final static int DELTA = 10;

    private String kind;
    private Entity[] data;

    public Entity[] getData() {
      return data;
    }

    public void setData(Entity[] data) {
      this.data = data.clone();
    }

    public void setKind(String kind) {
      this.kind = kind;
    }

    public FindChildrenJob(String name) {
      super(name);
    }

    protected IStatus run(IProgressMonitor monitor) {
      int fullSize = data.length;
      int numOfIterations = fullSize / DELTA;
      if (fullSize % DELTA != 0) {
        numOfIterations += 1;
      }

      int delta = DELTA;

      for (int i = 1; i <= numOfIterations; i++) {
        int beginIndex = (numOfIterations - 1) * delta;
        int lastIndex = numOfIterations * delta - 1 > fullSize - 1 ? fullSize - 1
            : numOfIterations * delta - 1;

        Entity[] subarray = null;
        if (beginIndex != lastIndex) {
          int length = lastIndex - beginIndex + 1;
          subarray = new Entity[length];
          System.arraycopy(data, beginIndex, subarray, 0, length);
        } else {
          subarray = new Entity[] { data[lastIndex] };
        }

        ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(
            getAppId()));
        findAllChildren(subarray);
        // refresh();
      }

      return Status.OK_STATUS;
    }

    private void findAllChildren(Entity[] entities) {
      Request r = new Request();
      Sort s = new Sort("", false);

      for (int i = 0; i < entities.length; i++) {
        if (entities[i].getKey() != null) {
          Filter f = new Filter("ONPOSITIVE_FILTER_FOR_PARENT_KEY",
              Filter.EQUAL, entities[i].getKey());// "ONPOSITIVE_FILTER_FOR_PARENT_KEY"

          Query q = new Query(new Filter[] { f }, s, 4, 0);
          Request.ViewRequestPart vrp = new Request.ViewRequestPart(
              kind, q, 4, namespace);
          r.addPart(vrp);
        }
      }

      ChildrenExtractingCallback cb = new ChildrenExtractingCallback();
      try {
        communicate(r, cb, new NullProgressMonitor());
      } catch (IOException e) {
        if (!(e instanceof EOFException)) {
          DataStoreTableUI
              .showErrorDialog("The following errr was occured:"
                  + e.getLocalizedMessage());
        }
      }

    }

    private class ChildrenExtractingCallback implements Callback {

      public boolean objectFetched(Object object) {
        if (object instanceof Entity) {
          Entity p = (Entity) object;
          if (p != null) {
            if (children.containsKey(kind)) {
              HashMap m = (HashMap) children.get(kind);
              Key par = p.getParent();
              if (m.containsKey(par)) {
                Collection c = (Collection) m.get(par);
                if (!c.contains(p)) {
                  c.add(p);
                }
              } else {
                ArrayList a = new ArrayList();
                a.add(p);
                m.put(par, a);
              }
            } else {
              HashMap m = new HashMap();
              ArrayList a = new ArrayList();
              a.add(p);
              m.put(p.getParent(), a);
              children.put(kind, m);
            }
            IDataCallback refresh = BaseDataFacade.this.refreshCallback;
            if (refresh != null) {
              refresh.lookChanged(null);
            }
          }
        }
        return true;
      }

    }

  }

  private final class FindParentsJob extends Job {

    private Entity[] data;
    private final static int DELTA = 10;

    public Entity[] getData() {
      return data;
    }

    public void setData(Entity[] data) {
      this.data = data.clone();
    }

    public FindParentsJob(String name) {
      super(name);
    }

    protected IStatus run(IProgressMonitor monitor) {

      int fullSize = data.length;
      int numOfIterations = fullSize / DELTA;
      if (fullSize % DELTA != 0) {
        numOfIterations += 1;
      }

      int delta = DELTA;

      for (int i = 1; i <= numOfIterations; i++) {
        int beginIndex = (/* numOfIterations */i - 1) * delta;
        int lastIndex = numOfIterations * delta - 1 > fullSize - 1 ? fullSize - 1
            : numOfIterations * delta - 1;

        Entity[] subarray = null;
        if (beginIndex != lastIndex) {
          int length = lastIndex - beginIndex + 1;
          subarray = new Entity[length];
          System.arraycopy(data, beginIndex, subarray, 0, length);
        } else {
          subarray = new Entity[] { data[lastIndex] };
        }

        ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(
            getAppId()));
        findParents(subarray);
      }

      // refresh();
      return Status.OK_STATUS;
    }

    private void findParents(Entity[] entities) {
      ArrayList<Key> parents = new ArrayList();

      for (int i = 0; i < entities.length; i++) {
        if (entities[i].getParent() != null) {
          parents.add(entities[i].getParent());
        }
      }

      if (parents.size() == 0) {
        return;
      }

      Request r = new Request();
      r.addPart(new Request.GetRequestPart(parents, parents.size(),
          namespace));
      ParentExtractingCallback pexc = new ParentExtractingCallback();
      try {
        communicate(r, pexc, new NullProgressMonitor());
      } catch (IOException e) {
        DataStoreTableUI
            .showErrorDialog("The following errr was occured:"
                + e.getLocalizedMessage());
      }

    }

    private class ParentExtractingCallback implements Callback {

      public boolean objectFetched(Object object) {
        if (object instanceof Entity) {
          Entity p = (Entity) object;
          if (p != null) {
            parents.put(p.getKey(), p);
            // refresh();
            IDataCallback refresh = BaseDataFacade.this.refreshCallback;
            if (refresh != null) {
              refresh.lookChanged(null);
            }
          }
        }
        return true;
      }

    }
  }

  private final class QueryJob extends Job {
    public final static int MIN_ENTITIES_COUNT = 50;

    private final class OrRunnable implements Runnable {

      private final IComplexQueryRequest z;
      private Boolean completed;
      private HashSet<Object> results = new HashSet<Object>();

      private OrRunnable(IComplexQueryRequest z) {
        this.z = z;
      }

      public void run() {
        z.execute(new IComplexFacade() {

          public void query(String kind, Query req, Callback cb,
              IProgressMonitor monitor) {
            try {
              BaseDataFacade fac = new BaseDataFacade(kind,
                  getProject(), debug);
              fac.setNamespace(namespace);
              fac.query(req, cb, monitor);
            } catch (Exception e) {
              e.printStackTrace();
            }
          }

        }, new Callback() {

          public boolean objectFetched(Object object) {
            if (object instanceof State) {
              State c = (State) object;
              completed = c.completed;
            } else {
              results.add(object);
            }
            return false;
          }

        }, new NullProgressMonitor());
      }
    }

    private final IDataCallback callback;
    private final Query query;

    private QueryJob(String name, IDataCallback callback, Query query) {
      super(name);
      this.callback = callback;
      this.query = query;
    }

    boolean isSimple(Query q) {
      for (Filter f : q.filters) {
        if (f.kind != Filter.EQUAL) {
          if (q.filters.length == 1) {
            if (f.kind != Filter.COMPLEX_FILTER) {
              return true;
            } else {
              return false;
            }
          }
          return false;
        }
      }
      return true;
    }

    protected IStatus run(IProgressMonitor monitor) {
      setStatus("Querying");
      completed = false;
      Request r = new Request();
      r.addPart(new Request.ViewRequestPart(kind, query,
          limit != -1 ? limit + 1 : -1, namespace));

      ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(
          getAppId()));
      callback.start();

      final ArrayList<Entity> results = new ArrayList<Entity>();
      objects.clear();
      ReadCallback cb = new ReadCallback(callback, results, fieldsMap,
          objects);

      int code = executeDataStoreQuery(monitor, r, cb);
      if (code < 0) {
        return Status.OK_STATUS;
      }

      Field[] determineFields = determineFields(cb.allEntities, fieldsMap);
      for (Field f : determineFields) {
        if (f.name.equals(Entity.KEY_RESERVED_PROPERTY)) {
          f.setType(Key.class);
        } else if (f.getType() == null) {
          f.setType(null);// String.class);
        }
      }

      List determinedFields = new ArrayList(
          Arrays.asList(determineFields));
      String kkk = "";
      ArrayList<Field> ppp = new ArrayList();
      if ((kkk = containsParentKey(cb.allEntities
          .toArray(new Entity[cb.allEntities.size()]))) != null) {
        PGAEField parent = new PGAEField("Parent", true);
        parent.setType(Entity.class);// Key.class);
        parent.setKeyKind(kkk);
        determinedFields.add(parent);
        ppp.add(parent);
      }
      pFields = ppp.toArray(new Field[ppp.size()]);

      FindChildrenJob[] forEachKind = new FindChildrenJob[kind.length()];
      int i = 0;
      ArrayList<Field> fff = new ArrayList();
      for (Iterator<String> itt = kindsOfChildren.keySet().iterator(); itt
          .hasNext();) {
        String varName = itt.next();
        String kkind = kindsOfChildren.get(varName);
        // if(!kkk.equals(kkind)){
        if (ppp != null && ppp.size() != 0) {
          String pKind = ((PGAEField) ppp.get(0)).getKeyKind();
          if (kkind != null && pKind != null && pKind.equals(kkind)) {
            continue;
          }
        }
        CGAEField child = new CGAEField(varName, true);
        child.setKind(kkind);
        child.setType(Entity.class);// Key.class);
        determinedFields.add(child);
        forEachKind[i] = new FindChildrenJob(
            "Extracting all chindlren for <" + kkind + "> kind.");
        forEachKind[i].setData(cb.results.toArray(new Entity[cb.results
            .size()]));
        forEachKind[i].setSystem(false);
        forEachKind[i].setKind(kkind);
        fff.add(child);
        i++;
        // }
      }
      chFields = fff.toArray(new Field[fff.size()]);
      determineFields = (Field[]) determinedFields
          .toArray(new Field[determinedFields.size()]);

      callback.fieldsFetched(determineFields);
      ArrayList<Entity> results2 = cb.results;

      FindParentsJob fpj = new FindParentsJob("Filling the parents");
      fpj.setSystem(true);
      fpj.setData(cb.results.toArray(new Entity[cb.results.size()]));

      callback.objectsFetched(results2.toArray());

      if (completed) {
        setStatus("Completed: " + cb.allEntities.size()
            + " entities fetched"
            + (limit != -1 ? " (limit:" + limit + ")" : ""));
      } else {
        setStatus("Completed: " + cb.allEntities.size()
            + " of ? entities fetched"
            + (limit != -1 ? " (limit:" + limit + ")" : ""));
      }
      if (results.size() > 0) {
        Entity e = (Entity) results.get(0);
        if (pm != null) {
          pm.setAppId(e.getAppId());
        }
      }
      sheduleFinderJobs(fpj, forEachKind);
      return Status.OK_STATUS;
    }

    private int executeDataStoreQuery(IProgressMonitor monitor, Request r,
        ReadCallback cb) {
      if (!isSimple(query)) {
        executeComplex(monitor);
        // completed = true;
        return -1; // Status.OK_STATUS;
      }
      try {
        communicate(r, cb, monitor);
      } catch (IOException e) {
        callback.failed(e);
      }
      if (cb.cm != null) {
        completed = cb.cm.completed && !cb.reachedLimit;
      }
      if (cb.cm != null && cb.cm.message != null) {
        if (cb.cm.trace
            .startsWith("com.google.appengine.api.datastore.DatastoreNeedIndexException")) {
          // let's attempt to remove sorting first
          if (query.sort != null && query.sort.property != null
              && query.sort.property.length() > 0) {
            callback.removeSort();
            query.sort = new Sort("", false);
            Thread thread = new Thread() {
              public void run() {
                query(query, callback);
              }
            };
            thread.setDaemon(true);
            thread.start();
            return -1;// return Status.OK_STATUS;
          } else {
            callback.failed(cb.cm.message);
          }
        } else {
          callback.failed(cb.cm.message);
        }

      }
      return 0;
    }

    private void sheduleFinderJobs(FindParentsJob fpj,
        FindChildrenJob[] fech) {
      cleanup();

      fpj.schedule();
      for (Job j : fech) {
        if (j != null) {
          j.schedule();
        }
      }
    }

    private String containsParentKey(Entity[] entities) {
      boolean flg = false;
      for (Entity entity : entities) {
        if (entity.getParent() != null) {
          return entity.getParent().getKind();
        }
      }
      return null;
    }

    private void executeComplex(IProgressMonitor monitor) {
      callback.start();
      ArrayList<Filter> eqFilters = new ArrayList<Filter>();
      ArrayList<Filter> otherFilters = new ArrayList<Filter>();
      for (Filter a : query.filters) {
        if (a.kind == Filter.EQUAL) {
          eqFilters.add(a);
        } else {
          otherFilters.add(a);
        }
      }
      Query simpleQuery = new Query(
          eqFilters.toArray(new Filter[eqFilters.size()]), new Sort(
              "", true), limit, 0);
      ArrayList<IComplexQueryRequest> s = new ArrayList<IComplexQueryRequest>();
      SimpleRequest simpleRequest = new SimpleRequest(kind, simpleQuery,
          limit);
      s.add(simpleRequest);
      for (Filter f : otherFilters) {
        IComplexQueryRequest m = toRequest(f);
        if (m == null) {
          Display.getDefault().syncExec(new Runnable() {

            public void run() {
              MessageDialog.openError(Display.getCurrent()
                  .getActiveShell(), "Error",
                  "Unable to parse reification request");
            }
          });
          return;
        }
        s.add(m);
      }
      ThreadPoolExecutor px = new ThreadPoolExecutor(5, 5, 10000,
          TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(
              1000));

      HashSet<OrRunnable> l = new HashSet<OrRunnable>();
      for (final IComplexQueryRequest z : s) {
        OrRunnable runnable = new OrRunnable(z);
        l.add(runnable);
        px.execute(runnable);
      }
      l2: while ((!monitor.isCanceled())
          && (px.getCompletedTaskCount() != l.size())) {
        {
          try {
            px.awaitTermination(100, TimeUnit.MILLISECONDS);
            for (OrRunnable m : l) {
              if (m.completed != null && m.completed == true) {
                break l2;
              } else {

              }
            }
          } catch (InterruptedException e) {
          }
        }
      }
      monitor.beginTask("Analyzing results", 10);
      px.shutdownNow();

      HashSet<OrRunnable> incompleted = new HashSet<OrRunnable>();
      HashSet<OrRunnable> completed = new HashSet<OrRunnable>();
      for (OrRunnable m : l) {
        if (m.completed != null && m.completed == true) {
          completed.add(m);
        } else {
          incompleted.add(m);
        }
      }

      if (completed.size() != 0) {
        OrRunnable z = completed.iterator().next();
        HashSet<Object> r = z.results;
        for (OrRunnable q : completed) {
          if (q != z) {
            r.retainAll(q.results);
          }
        }
        if (incompleted.size() != 0) {
          for (OrRunnable q : incompleted) {
            q.z.filter(r);
          }
        }
        ArrayList<Object> results = new ArrayList<Object>(r);
        if (query.sort.property != null
            && query.sort.property.length() > 0) {
          Collections.sort(results, new BaseViewer.SortComparator(
              query.sort.property, query.sort.ascending));
        }

        boolean b = results.size() > limit;
        if (b) {
          ArrayList<Object> m = new ArrayList<Object>(limit);
          for (int a = 0; a < limit; a++) {
            m.add(results.get(a));
          }
          results = m;
        }
        Field[] determineFields = determineFields(results, fieldsMap);
        callback.fieldsFetched(determineFields);
        callback.objectsFetched(results.toArray());
        if (!b) {
          setStatus("Completed: " + results.size()
              + " entities fetched"
              + (limit != -1 ? " (limit:" + limit + ")" : ""));
        } else {
          setStatus("Completed: " + results.size()
              + " of ? entities fetched"
              + (limit != -1 ? " (limit:" + limit + ")" : ""));
        }
        for (Object o : results) {
          if (o instanceof Entity) {
            objects.add((Entity) o);
          }
        }
      } else {
        setStatus("Unable to complete request");
      }
    }

    private IComplexQueryRequest toRequest(Filter f) {
      if (f.kind == Filter.COMPLEX_FILTER) {
        final ComplexFilter filter = (ComplexFilter) f.value;
        final Filter[] parseValue = filter.field.parseValue(filter);
        if (parseValue != null) {
          return new ReificationRequest(new SimpleRequest(
              filter.field.keyKind, new Query(parseValue,
                  new Sort("", false), limit, 0), limit),
              limit) {

            protected IComplexQueryRequest toQuery(Object object) {
              Entity e = (Entity) object;
              Key key = e.getKey();
              return new SimpleRequest(kind, new Query(
                  new Filter[] { new Filter(
                      filter.field.name, Filter.EQUAL,
                      key) }, new Sort("", true), 100,
                  100), 100);
            }

            public void filter(HashSet<Object> r) {
              waitWhileNotDone();
              HashSet<Object> toREtain = new HashSet<Object>();
              for (Object o : r) {
                Entity e = (Entity) o;
                String fName = filter.field.name;

                Object property = e.getProperty(fName);
                if (fName.equals(Entity.KEY_RESERVED_PROPERTY)) {
                  property = e.getKey();
                }

                if (property instanceof Collection) {
                  Collection c = (Collection) property;
                  for (Object o1 : c) {
                    if (matching.contains(property)) {
                      toREtain.add(o1);
                      break;
                    }
                  }
                } else {
                  if (matching.contains(property)) {
                    toREtain.add(o);
                  }
                }
              }
              r.retainAll(toREtain);
            }
          };
        }
        return null;
      }
      return new SimpleRequest(kind, new Query(new Filter[] { f },
          new Sort("", false), limit, 0), limit);
    }
  }

  private final class CommunnicationThread extends Thread {
    private final PostMethod postMethod;
    private final HttpClient client;
    Exception ex;

    private CommunnicationThread(PostMethod postMethod, HttpClient client) {
      this.postMethod = postMethod;
      this.client = client;
    }

    public void run() {

      try {
        client.executeMethod(postMethod);
        client.getState();
      } catch (HttpException e) {
        ex = e;
      } catch (IOException e) {
        ex = e;
      } finally {

      }
    }
  }

  protected final class ReadCallback implements Callback {
    protected final IDataCallback callback;
    protected final ArrayList<Entity> results;
    protected final ArrayList<Entity> allEntities;
    long startTime;
    boolean fetched;
    boolean reachedLimit;
    private LinkedHashMap<String, Field> fields;
    private State cm;

    public LinkedHashMap<String, Field> getFields() {
      return fields;
    }

    public void setFields(LinkedHashMap<String, Field> fields) {
      this.fields = fields;
    }

    public State getCm() {
      return cm;
    }

    public void setCm(State cm) {
      this.cm = cm;
    }

    public ArrayList<Entity> getResults() {
      return results;
    }

    protected ReadCallback(IDataCallback callback,
        ArrayList<Entity> results, LinkedHashMap<String, Field> fields,
        ArrayList<Entity> allEntities) {
      this.callback = callback;
      this.allEntities = allEntities;
      this.results = results;
      this.fields = fields;
    }

    public boolean objectFetched(Object object) {
      if (object instanceof State) {
        State c = (State) object;
        cm = c;
      }

      if (results.isEmpty()) {
        if (!fetched) {
          startTime = System.currentTimeMillis();
        }
      }
      long l0 = System.currentTimeMillis();
      int delta = (int) (((l0 - startTime) / 1000 + 1) % 5);
      if (object instanceof Entity) {
        if (allEntities.size() == limit) {
          reachedLimit = true;
          return false;
        }
        allEntities.add((Entity) object);
        results.add((Entity) object);

        if (delta == 0) {
          if (!fetched) {
            Field[] determineFields = BaseDataFacade.this
                .determineFields(results, fields);
            callback.fieldsFetched(determineFields);
            fetched = true;
          }
          setStatus("Querying: " + allEntities.size()
              + " of ? entities fetched"
              + (limit != -1 ? " (limit:" + limit + ")" : ""));
          callback.objectsFetched(results.toArray());
          results.clear();
        }
      }
      return false;
    }
  }

  public static interface CellEditorFactory {
    CellEditor createCellEditor();
  }

  private HashMap<String, HashSet<Object>> values = new HashMap<String, HashSet<Object>>();

  public class GAEField extends Field implements Comparable<GAEField> {

    public String toString() {
      return name
          + ":"
          + (getType() == null ? "Not_Specified" : getType()
              .getSimpleName());
    }

    public Filter[] parseValue(ComplexFilter filter) {
      String value = filter.value;
      int indexOf = value.indexOf('=');
      if (indexOf > 0) {
        String[] split = value.split(",");
        Filter[] result = new Filter[split.length];
        for (int a = 0; a < split.length; a++) {
          String vl = split[a].trim();
          int indexOf2 = vl.indexOf('=');
          if (indexOf2 != -1) {
            String fName = vl.substring(0, indexOf2);
            Object fValue = vl.substring(indexOf2 + 1).trim();
            String string = (String) fValue;
            if (string.charAt(0) == '"') {
              if (string.charAt(string.length() - 1) == '"') {
                fValue = string.substring(1,
                    string.length() - 1);
              }
            } else {
              try {
                if (string.indexOf('.') != -1) {
                  fValue = Double.parseDouble(string);
                } else
                  fValue = Long.parseLong(string);
              } catch (Exception e) {
              }
            }
            if (fValue.equals("true")) {
              fValue = Boolean.TRUE;
            }
            if (fValue.equals("false")) {
              fValue = Boolean.FALSE;
            }
            result[a] = new Filter(fName, Filter.EQUAL, fValue);
            // TODO FIX ME
          }
        }
        return result;
      } else if (keyKindDetails != null) {
        String[] split = value.split(",");
        Filter[] result = new Filter[split.length];
        if (split.length <= keyKindDetails.length) {
          for (int a = 0; a < split.length; a++) {
            String name = keyKindDetails[a];

            String vl = split[a].trim();
            Object fValue = vl;
            if (fValue.equals("true")) {
              fValue = Boolean.TRUE;
            }
            if (fValue.equals("false")) {
              fValue = Boolean.FALSE;
            }
            if (fValue.equals("<null>")) {
              fValue = null;
            }
            // TODO FIX ME
            result[a] = new Filter(name, Filter.EQUAL, fValue);
          }
          return result;
        }
      }
      return null;
    }

    protected HashMap<Key, String> details = new HashMap<Key, String>();

    public BaseDataFacade getFacade() {
      return BaseDataFacade.this;
    }

    public final class EnableDetailFormatting extends Action {
      private EnableDetailFormatting(String text) {
        super(text);
      }

      public void run() {
        enableDetailFormatting();
        // do it here
      }
    }

    private final class MyListener implements SelectionListener,
        ModifyListener {
      private final IFilterListener listener;
      private final ArrayList<Comparable> arrayList;
      private final Combo c;

      private MyListener(IFilterListener listener,
          ArrayList<Comparable> arrayList, Combo c) {
        this.listener = listener;
        this.arrayList = arrayList;
        this.c = c;
      }

      public void widgetSelected(SelectionEvent e) {
        int selectionIndex = c.getSelectionIndex();
        if (selectionIndex != -1) {
          if (selectionIndex == 0) {
            listener.clearFilter(name);

          } else {
            listener.filterValueChangedTo(name,
                arrayList.get(selectionIndex - 1));
          }
        }
      }

      public void widgetDefaultSelected(SelectionEvent e) {
        int selectionIndex = c.getSelectionIndex();

        if (selectionIndex != -1) {
          if (selectionIndex == 0) {
            listener.clearFilter(name);

          } else {

            listener.filterValueChangedTo(name,
                arrayList.get(selectionIndex - 1));
          }
        }
      }

      public void modifyText(ModifyEvent e) {
        if (c.getSelectionIndex() == -1) {
          listener.filterValueChangedTo(name, c.getText());
        }
      }
    }

    String keyKind;

    protected String[] keyKindDetails;

    public String[] getKeyKindDetails() {
      return keyKindDetails;
    }

    public void adjustDetailFormatting() {
      synchronized (details) {
        details.clear();
      }
      refreshCallback.lookChanged(null);
    }

    boolean multiplicity;

    public String getKeyKind() {
      return keyKind;
    }

    public void setKeyKind(String keyKind) {
      this.keyKind = keyKind;
    }

    protected GAEField(String name, boolean needsresize) {
      super(name, needsresize);
      keyKindDetails = KeyFormat.getKeyFormat(getAppId(), kind, name);
    }

    public BaseDataFacade createFacade(String kind) {
      BaseDataFacade baseDataFacade = new BaseDataFacade(kind, project,
          debug) {

        public boolean isCompleted() {
          return false;
        }

      };
      baseDataFacade.setNamespace(namespace);
      baseDataFacade.setLimit(limit);
      return baseDataFacade;
    }

    public BaseDataFacade createFacade(String kind, IDataCallback cb,
        ISingleCallback call) {
      BaseDataFacade baseDataFacade = new BaseDataFacade(kind, project,
          pm, debug, cb, call) {

        public boolean isCompleted() {
          return false;
        }

      };
      baseDataFacade.setLimit(limit);
      return baseDataFacade;
    }

    public String getTitle() {
      StringBuilder title = new StringBuilder();
      title.append(name);
      if (getType() != null) {
        title.append('(');
        String tName = getType().getSimpleName();
        title.append(tName);
        if (getType() == Key.class) {
          if (keyKind != null) {
            title.append(" to ");
            title.append(keyKind);
          }
        }
        title.append(')');
      } else {
        title.append('(');
        title.append("not specified");
        title.append(')');
      }
      if (multiplicity) {
        title.append('*');
      }
      return title.toString();
    }

    public Image getImage(Object object) {
      if (name.equals(Entity.KEY_RESERVED_PROPERTY)) {
        return BaseImages.entityImage;
      }
      return null;
    }

    public int getPreferedHeightInPixels(Object object) {
      return 0;
    }

    public int getPreferedWidthInPixels() {
      return 0;
    }

    public String getText(Object object) {
      Entity r = (Entity) object;
      Object property = r.getProperty(name);
      if (name.equals(Entity.KEY_RESERVED_PROPERTY)) {
        property = r.getKey();
      }
      if (property == null) {
        if (!r.hasProperty(name)) {
          return "<missing>";
        }
      }
      if (property instanceof Blob) {
        Object property2 = r
            .getProperty(ONPOSITIVE_MAGIC_SHORTENED_PROPERTIES);
        if (property2 != null) {
          String v = (String) property2;
          String[] split = v.split(",");
          for (String s : split) {
            int indexOf = s.indexOf('=');
            String key = s.substring(0, indexOf);
            String value = s.substring(indexOf + 1);
            if (key.equals(name)) {
              return value;
            }
          }
        }
      }
      String objectText = getObjectText2(object, property);
      return objectText;
    }

    public String getObjectText2(Object object, Object property) {
      if (property instanceof Collection<?>) {
        Collection<?> c = (Collection<?>) property;
        StringBuilder r = new StringBuilder();
        int s = c.size();
        int a = 0;
        r.append('[');
        for (Object o : c) {
          r.append(getObjectText2(object, o));
          if (a != s - 1) {
            r.append(',');
          }
          a++;
        }
        r.append(']');
        return r.toString();
      }
      if (property instanceof Key) {
        if (keyKindDetails != null) {

          String string = details.get(property);
          if (string != null) {
            return string;
          }
          sheduleDetails(object, property);
        }
      }
      String objectText = getObjectText(property);
      return objectText;
    }

    class DetailsFetcher {

      HashSet<Key> sheduled = new HashSet<Key>();

      Thread currentScheduler;

      synchronized void shedule(Object object, Key property) {
        if (currentScheduler == null) {
          currentScheduler = new Thread() {

            public void run() {

              try {
                Thread.sleep(500);
                capture();
              } catch (InterruptedException e) {
              } finally {
                currentScheduler = null;
              }
            }
          };
          currentScheduler.setDaemon(true);
          currentScheduler.start();
        }
        sheduled.add(property);
      }

      protected void capture() {
        HashSet<Key> toFetch = new HashSet<Key>();
        synchronized (this) {
          toFetch.addAll(sheduled);
          sheduled.clear();
        }
        // FIXME
        BaseDataFacade baseDataFacade = new BaseDataFacade(keyKind,
            BaseDataFacade.this.getProject(), isDebug());
        baseDataFacade.setNamespace(namespace);
        Collection<Entity> fetch;
        try {
          fetch = baseDataFacade.fetch(toFetch,
              new NullProgressMonitor());

          synchronized (details) {
            for (Entity e : fetch) {
              Key c = e.getKey();
              String[] ca = keyKindDetails;
              if (ca != null) {
                StringBuilder stringBuilder = new StringBuilder();
                int a = 0;
                for (String s : ca) {
                  stringBuilder.append(getObjectText(e
                      .getProperty(s)));
                  if (a != ca.length - 1) {
                    stringBuilder.append(',');
                  }
                  a++;
                }

                details.put(c, stringBuilder.toString());
              }
            }
            BaseDataFacade.this.refreshCallback.lookChanged(null);
          }
        } catch (IOException e1) {
          e1.printStackTrace();
        }
      }
    }

    DetailsFetcher fs = new DetailsFetcher();

    private void sheduleDetails(Object object, Object property) {
      fs.shedule(object, (Key) property);
    }

    private String getObjectText(Object property) {
      if (property instanceof Collection<?>) {
        Collection<?> c = (Collection<?>) property;
        StringBuilder r = new StringBuilder();
        int s = c.size();
        int a = 0;
        r.append('[');
        for (Object o : c) {
          r.append(getObjectText(o));
          if (a != s - 1) {
            r.append(',');
          }
          a++;
        }
        r.append(']');
        return r.toString();
      }
      if (property != null) {

        if (property instanceof Email) {
          Email m = (Email) property;
          return m.getEmail();
        }
        if (property instanceof Category) {
          Category m = (Category) property;
          return m.getCategory();
        }
        if (property instanceof Link) {
          Link m = (Link) property;
          return m.getText();
        }
        if (property instanceof PhoneNumber) {
          PhoneNumber m = (PhoneNumber) property;
          return m.getNumber();
        }
        if (property instanceof PostalAddress) {
          PostalAddress m = (PostalAddress) property;
          return m.getAddress();
        }
        if (property instanceof Rating) {
          Rating m = (Rating) property;
          return m.getRating() + "";
        }
        if (property instanceof Date) {
          return dt.format(property);
        }
        NumberFormat instance = getNumberFormat();

        if (property instanceof Long) {
          return instance.format(property);
        }
        if (property instanceof Double) {
          return instance.format(property);
        }
        String string = property.toString();
        return string;
      }
      return "<null>";
    }

    private NumberFormat getNumberFormat() {
      return format;
    }

    public Object getValue(Object f) {
      Entity m = (Entity) f;
      return m.getProperty(name);
    }

    public int compare(Object o1, Object o2) {
      return o1.toString().compareTo(o2.toString());
    }

    private String cText;

    public Control createFilterControl(Composite filters) {
      /*
       * if (name.equals(Entity.KEY_RESERVED_PROPERTY)) { Composite c =
       * new Composite(filters, SWT.NONE); GridLayout layout = new
       * GridLayout(1, false); layout.marginHeight = 0;
       * c.setLayout(layout); Link link = new Link(c, SWT.NONE);
       * link.setText("<a>Filters and actions:</a>");
       * link.setLayoutData(GridDataFactory.fillDefaults()
       * .align(GridData.END, GridData.CENTER).grab(true, true)
       * .create()); return c; }
       */
      if (getType() == null
          || !Comparable.class.isAssignableFrom(getType())) {
        Label label = new Label(filters, SWT.NONE);
        label.setText("  ");
        return label;
      }

      final Composite c = new Composite(filters, SWT.BORDER);
      GridLayout layout = new GridLayout(2, false);
      layout.marginWidth = 0;
      layout.marginHeight = 0;
      layout.horizontalSpacing = 0;
      c.setLayout(layout);
      final Text ts = new Text(c, SWT.NONE);
      ts.setLayoutData(GridDataFactory.fillDefaults().grab(true, true)
          .create());
      ts.addFocusListener(new FocusListener() {

        ToolBar t;
        private ControlDecoration controlDecoration;

        public void focusLost(FocusEvent e) {
          t.dispose();
          ts.setLayoutData(GridDataFactory.fillDefaults()
              .grab(true, true).indent(0, 0).create());
          ts.setTopIndex(0);
          controlDecoration.dispose();
          c.layout(true);
        }

        public void focusGained(FocusEvent e) {
          c.setRedraw(false);
          try {
            t = new ToolBar(c, SWT.NONE);
            ts.setLayoutData(GridDataFactory.fillDefaults()
                .grab(true, true).indent(9, 0).create());
            t.setLayoutData(GridDataFactory.fillDefaults()
                .grab(false, true).create());
            ts.setTopIndex(0);
            final ToolItem ma = new ToolItem(t, SWT.DROP_DOWN);
            controlDecoration = new ControlDecoration(ts, SWT.TOP
                | SWT.LEFT);
            FieldDecoration dec = FieldDecorationRegistry
                .getDefault()
                .getFieldDecoration(
                    FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
            c.layout(true);
            ma.addSelectionListener(new SelectionListener() {

              public void widgetSelected(SelectionEvent e) {
                if (e.detail == SWT.ARROW) {
                  MenuManager mc = new MenuManager();
                  if (getType() == Key.class
                      && keyKind != null
                      && keyKind.length() > 0
                      && keyKindDetails == null) {
                    mc.add(new EnableDetailFormatting(
                        "Enable detail formatting"));
                  }
                  if (getType() == Key.class
                      && keyKind != null
                      && keyKind.length() > 0
                      && keyKindDetails != null) {
                    mc.add(new Action(
                        "Disable detail formatting") {

                      public void run() {
                        disableDetailFormatting();
                      }
                    });
                  }
                  final Menu createContextMenu = mc
                      .createContextMenu(ma.getParent());
                  Point cursorLocation = Display.getCurrent()
                      .getCursorLocation();
                  createContextMenu
                      .setLocation(cursorLocation);
                  createContextMenu.setVisible(true);
                  createContextMenu
                      .addMenuListener(new MenuListener() {

                        public void menuShown(
                            MenuEvent e) {

                        }

                        public void menuHidden(
                            MenuEvent e) {
                          Display.getCurrent()
                              .asyncExec(
                                  new Runnable() {

                                    public void run() {
                                      createContextMenu
                                          .dispose();

                                    }
                                  });

                        }
                      });
                } else {
                  resync();
                }
              }

              public void widgetDefaultSelected(SelectionEvent e) {
                resync();
              }
            });

            ma.setToolTipText("Refilter");
            controlDecoration.setImage(dec.getImage());

            ma.setImage(DataViewPart.choose);
          } finally {
            c.setRedraw(true);
          }
          // ma.setText("...");

        }
      });
      cText = "";
      IControlContentAdapter controlContentAdapter = new TextContentAdapter();
      IContentProposalProvider proposalProvider = new IContentProposalProvider() {

        public IContentProposal[] getProposals(String contents,
            int position) {
          contents = contents.trim();
          HashSet<Object> hashSet = values.get(name);
          ArrayList<Object> o = new ArrayList<Object>(hashSet);
          try {
            Collections.sort((List) o);
          } catch (Exception e) {
          }
          ArrayList sa = new ArrayList();

          for (Object obj : o) {
            if (obj instanceof Key) {
              if (keyKindDetails != null) {
                String s = details.get(obj);
                if (s != null
                    && s.toLowerCase().startsWith(
                        contents.toLowerCase())) {
                  BasicContentProposal p = new BasicContentProposal(
                      s, s, null, s.length(), obj);
                  sa.add(p);
                } else {
                  s = getObjectText(obj);
                  if (s.toLowerCase().startsWith(
                      contents.toLowerCase())) {
                    BasicContentProposal p = new BasicContentProposal(
                        s, s, null, s.length(), obj);
                    sa.add(p);
                  }
                }
              }
            } else {
              String s = getObjectText(obj);
              if (s.toLowerCase().startsWith(
                  contents.toLowerCase())) {
                BasicContentProposal p = new BasicContentProposal(
                    s, s, null, s.length(), obj);
                sa.add(p);
              }
            }
          }
          IContentProposal[] result = new IContentProposal[sa.size()];
          sa.toArray(result);

          return result;
        }
      };
      ContentAssistCommandAdapter contentAssistCommandAdapter = new ContentAssistCommandAdapter(
          ts, controlContentAdapter, proposalProvider, null, null);
      contentAssistCommandAdapter
          .setProposalAcceptanceStyle(ContentAssistCommandAdapter.PROPOSAL_REPLACE);
      contentAssistCommandAdapter.setAutoActivationCharacters(null);
      ts.addSelectionListener(new SelectionListener() {

        public void widgetSelected(SelectionEvent e) {

        }

        public void widgetDefaultSelected(SelectionEvent e) {
          resync();
        }
      });
      ts.addModifyListener(new ModifyListener() {

        public void modifyText(ModifyEvent e) {
          String txt = ts.getText();
          cText = txt;
        }

      });
      Object filter = BaseDataFacade.this.getCurrentQuery().getFilter(
          name);
      if (filter != null) {
        ts.setText(getObjectText(filter));
      }
      return c;
    }

    protected void resync() {
      refresh();
    }

    public void updateFilterControl(final String key, Control combo,
        final IFilterListener listener) {

      Class<?> type = getType();
      if (type == null || !Comparable.class.isAssignableFrom(getType())) {
        return;
      }
      if (type == String.class) {

      }
      // HashSet<Object> vals = values.get(key);
      // if (vals == null) {
      // vals = new HashSet<Object>();
      // }
      // vals.remove(null);
      // Object currentValue = null;
      // boolean containsKey = hasFilter(key);
      // if (containsKey) {
      // currentValue = getFilter(key);
      // } else {
      // currentValue = new Any();
      // }
      // final ArrayList<Comparable> arrayList = new
      // ArrayList<Comparable>(
      // (HashSet) vals);
      // Collections.sort(arrayList);
      // arrayList.add(null);
      // String[] values = new String[arrayList.size() + 1];
      // if (combo instanceof Combo) {
      // values[0] = "<Any>";
      // int size = arrayList.size();
      // for (int a = 0; a < size; a++) {
      // values[a + 1] = arrayList.get(a) != null ?
      // getObjectText(arrayList
      // .get(a))
      // : "<null>";
      // }
      // final Combo c = (Combo) combo;
      // Object data = c.getData("listener");
      // if (data != null) {
      // c.removeSelectionListener((SelectionListener) data);
      // c.removeModifyListener((ModifyListener)data);
      // c.setData("listener",null);
      // }
      // MyListener listener2 = new MyListener(listener, arrayList, c);
      // c.setItems(values);
      // int selectIndex = 0;
      // if (currentValue instanceof Any) {
      // selectIndex = 0;
      // } else
      // for (int a = 0; a < size; a++) {
      // Object ca = arrayList.get(a);
      // if ((ca == null && currentValue == null)
      // || (ca != null && ca.equals(currentValue))) {
      // selectIndex = a + 1;
      // }
      // }
      // if (currentValue != null&&(!(currentValue instanceof Any))) {
      // if (selectIndex != -1) {
      // c.select(selectIndex);
      // }
      // else{
      // c.setText(getObjectText(currentValue));
      // }
      // } else {
      // int selectionIndex = c.getSelectionIndex();
      // if (selectionIndex!=selectIndex){
      // c.select(selectIndex);
      // }
      // }
      // if (c.getData("listener") == null) {
      // c.addSelectionListener(listener2);
      // c.setData("listener", listener2);
      // c.addModifyListener(listener2);
      // }
      //
      // }
    }

    public boolean isKey() {
      return name.equals(Entity.KEY_RESERVED_PROPERTY);
    }

    public GAEField getSingleField() {
      GAEField gaeField = new GAEField(name, false);
      gaeField.setType(this.getType());
      gaeField.setKeyKind(this.getKeyKind());
      return gaeField;
    }

    public IProject getProject() {
      return project.getProject();
    }

    public int rating() {
      if (this.isKey()) {
        return 0;
      }
      if (getType() == null) {
        return 10;
      }
      if (this.multiplicity) {
        return 6;
      }
      if (this.getType() == Key.class) {
        return 1;
      }
      if (this.getType() == String.class) {
        return 2;
      }
      if (Number.class.isAssignableFrom(this.getType())) {
        return 3;
      }
      if (Comparable.class.isAssignableFrom(this.getType())) {
        return 4;
      }
      return 5;
    }

    public int compareTo(GAEField o) {
      int i = this.rating() - o.rating();
      if (i == 0) {
        return this.name.compareTo(o.name);
      }
      return i;
    }

    private BaseDataFacade getOuterType() {
      return BaseDataFacade.this;
    }

    public void enableDetailFormatting() {
      DataStoreTableUI dataStoreTableUI = new DataStoreTableUI();
      dataStoreTableUI.setFacade(BaseDataFacade.this);
      String[] openDetailDialog = dataStoreTableUI
          .openDetailDialog(keyKind);
      KeyFormat.setKeyFormat(getAppId(), kind, keyKind, openDetailDialog);
      keyKindDetails = openDetailDialog;
      adjustDetailFormatting();
    }

    public void disableDetailFormatting() {
      KeyFormat.setKeyFormat(getAppId(), kind, keyKind, null);
      keyKindDetails = null;
      adjustDetailFormatting();
    }
  }

  public class PGAEField extends GAEField {

    protected PGAEField(String name, boolean needsresize) {
      super(name, needsresize);
    }

    public boolean isKey() {
      return false;
    }

    public String getText(Object object) {
      Entity e = (Entity) object;
      Key parent = e.getParent();
      if (parents.containsKey(parent)) {
        Entity pe = ((Entity) parents.get(parent));
        String objText = pe.getKey().toString();
        if (keyKindDetails != null) {
          objText = "";
          int cch = 0;
          for (String sKKD : keyKindDetails) {
            objText += getObjectText2(pe, pe.getProperty(sKKD));
            if (cch != keyKindDetails.length - 1) {
              objText += ";";
            }
          }

        }
        return objText;// ((Entity)
        // parents.get(parent)).getKey().toString();//
        // getKind();
      }
      return "{unknown}";
    }

    public Object getValue(Object f) {
      Entity m = (Entity) f;
      return parents.get(m);
    }

    public String getTitle() {
      StringBuilder title = new StringBuilder();
      title.append(name);
      return title.toString();
    }
  }

  public class CGAEField extends PGAEField {

    private String kind;

    public void setKind(String kind) {
      setKeyKind(kind);
      this.kind = kind;
    }

    private CGAEField(String name, boolean needsresize) {
      super(name, needsresize);
      multiplicity = true;
    }

    public String getTitle() {
      StringBuilder title = new StringBuilder();
      title.append(name);
      title.append("(");
      title.append(kind);
      title.append(")");
      return title.toString();
    }

    public GAEField getSingleField() {
      GAEField gaeField = new CGAEField(name, false);
      gaeField.setType(this.getType());
      gaeField.setKeyKind(this.getKeyKind());
      gaeField.multiplicity = false;
      return gaeField;
    }

    public boolean isKey() {
      return false;
    }

    public String getText(Object object) {
      Entity e = (Entity) object;

      if (children.containsKey(kind)) {
        HashMap m = (HashMap) children.get(kind);
        if (m.containsKey(e.getKey())) {
          Collection c = (Collection) m.get(e.getKey());
          String end = "}";
          StringBuilder sb = new StringBuilder();
          sb.append("{");
          int ch = 0;
          for (Iterator i = c.iterator(); i.hasNext();) {
            if (ch > 2) {
              sb.append("...");
              break;
            }
            Entity pe = (Entity) i.next();
            // sb.append(pe.getKey());//KeyFactory.keyToString(pe.getKey()));
            String objText = pe.getKey().toString();
            if (keyKindDetails != null) {
              objText = "";
              int cch = 0;
              for (String sKKD : keyKindDetails) {
                objText += getObjectText2(pe,
                    pe.getProperty(sKKD));
                if (cch != keyKindDetails.length - 1) {
                  objText += ";";
                }
              }

            }
            sb.append(objText);
            if (ch != c.size() - 1) {
              sb.append(",");
            }
            ch++;
          }
          sb.append(end);
          return sb.toString();
        }
      }
      return "{unknown}";
    }

    public Object getValue(Object f) {
      Entity m = (Entity) f;
      return ((HashMap) children.get(kind)).get(m.getKey());
    }

  }

  public BaseDataFacade(String kind2, IJavaProject project,
      DataViewPart dataViewPart, boolean isDebug,
      IDataCallback refreshCallback, ISingleCallback call) {
    this.kind = kind2;
    this.project = project;
    pm = dataViewPart;
    this.debug = isDebug;
    this.singleCall = call;
    this.refreshCallback = refreshCallback;
    init();
  }

  public Collection<Entity> fetch(Collection<Key> toFetch,
      IProgressMonitor monitor) throws IOException {
    completed = false;
    Request r = new Request();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    r.addPart(new Request.GetRequestPart(toFetch, limit != -1 ? limit + 1
        : -1, namespace));

    final ArrayList<Entity> results = new ArrayList<Entity>();
    objects.clear();
    Callback cb = new Callback() {

      public boolean objectFetched(Object object) {
        if (object instanceof Entity) {
          results.add((Entity) object);
        }
        return true;
      }
    };
    communicate(r, cb, monitor);
    return results;
  }

  protected void init() {

    if (project != null) {
      ProjectMiner projectMiner = new ProjectMiner(kind, project);
      kindsOfChildren = projectMiner
          .findAllPossibleRelatedKindsForThisKind();
      persistentFields = projectMiner
          .findAllPossibleFields(kindsOfChildren.keySet());
      embeddedFields = (HashMap<String, FieldInfo>) projectMiner
          .getEmbeddedFields();
    }
    parents = Collections.synchronizedMap(new HashMap());
    children = Collections.synchronizedMap(new HashMap());

    return;
  }

  private void cleanup() {
    if (parents != null) {
      parents.clear();
    }
    if (children != null) {
      children.clear();
    }
  }

  public BaseDataFacade(String kind2, IJavaProject project,
      DataViewPart dataViewPart, boolean isDebug) {
    this.kind = kind2;
    this.project = project;
    pm = dataViewPart;
    this.debug = isDebug;
    init();
  }

  public BaseDataFacade(String string, IJavaProject project2, boolean b) {
    this.kind = string;
    this.project = project2;
    this.debug = b;
    init();
  }

  public Object getFilter(String key) {
    if (lastQuery != null) {
      return lastQuery.getFilter(key);
    }
    return null;
  }

  public boolean hasFilter(String key) {
    if (lastQuery != null) {
      return lastQuery.hasFilter(key);
    }
    return false;
  }

  public void add(Object object, OperationCallback callback) {
    Request r = new Request();
    Entity ee = (Entity) object;
    Key eek = ee.getKey();
    try {
      // java.lang.reflect.Field appIdNs = ee.getKey().getClass()
      // .getDeclaredField("appIdNamespace");
      // java.lang.reflect.Field fs1 = appIdNs.getType().getDeclaredField(
      // "namespace");
      // fs1.setAccessible(true);
      // appIdNs.setAccessible(true);
      // fs1.set(appIdNs.get(eek), namespace);
      r.addPart(new Request.AddRequestPart(object, namespace));
      try {
        communicate(r, null, new NullProgressMonitor());
        callback.passed(object);
      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public interface Callback {
    boolean objectFetched(Object object);
  }

  public Object[] communicate(Request request, Callback cb,
      IProgressMonitor monitor) throws IOException {
    try {
      // pre process request here if needed;
      //
      monitor.beginTask("Initiating communication", 100);
      for (RequestPart p : request.parts) {
        p.preprocess(monitor);
      }
      ByteArrayOutputStream b = new ByteArrayOutputStream();
      DataOutputStream s = new DataOutputStream(b);
      String sessionCode = null;
      String applicationId = getAppId();
      try {
        sessionCode = SessionManager.getSessionCode(applicationId,
            debug);

      } catch (BadUserIdException e1) {
        return null;
      }
      if (sessionCode == null) {
        sessionCode = "";
      }
      s.writeUTF(sessionCode);
      request.write(s);
      s.close();

      InputStream communicate = communicate(b.toByteArray(), cb, monitor);
      if (monitor != null && monitor.isCanceled()) {
        return null;
      }
      if (monitor != null) {
        monitor.beginTask("Retrieving results", 30);
      }
      try {
        DataInputStream ds = new DataInputStream(communicate);
        int readInt = ds.readInt();
        String logMessage = "Query: (" + applicationId + sessionCode
            + "," + readInt + "," + skipReconnect + ")";

        Activator.getDefault().getLog()
            .log(new Status(0, Activator.PLUGIN_ID, logMessage));
        System.out.println(logMessage);

        if (readInt == 200) {
          return request.parse(ds, cb, monitor);
        }
        if (readInt == 500) {
          String appId = GaeBridge.getAppId(project.getProject());
          String version = GaeBridge.getVersion(project.getProject());

          SessionManager.removeSessionCode(appId, sessionCode);

          boolean estabilishSession = false;
          if (!skipReconnect) {
            Activator
                .getDefault()
                .getLog()
                .log(new Status(0, Activator.PLUGIN_ID,
                    "Trying to establish session for ("
                        + appId + "," + version + ")"));
            estabilishSession = SessionManager.estabilishSession(
                appId, version);
          }

          if (estabilishSession) {
            return communicate(request, cb, monitor);
          }
          return new Object[] {};
        }
        throw new IOException("Unknown response");
      } finally {
        // communicate.close();
      }
    } catch (Exception e) {
      if (e instanceof IOException) {
        throw (IOException) e;
      } else
        throw new IOException(e.getMessage());
    }
  }

  protected InputStream communicate(final byte[] content, Callback cb,
      IProgressMonitor monitor) throws Exception {
    String url = getUrl();
    if (url == null) {
      return null;
    }
    final PostMethod postMethod = new PostMethod(url);
    postMethod.setRequestEntity(new MultipartRequestEntity(
        new Part[] { new Part() {

          public String getCharSet() {
            return CHARSET;
          }

          public String getContentType() {
            return "class";
          }

          public String getName() {
            return "item";
          }

          public String getTransferEncoding() {
            return CHARSET;
          }

          protected long lengthOfData() throws IOException {
            return content.length;
          }

          protected void sendData(OutputStream out)
              throws IOException {
            out.write(content);
          }

        } }, new HttpMethodParams()));
    final HttpClient client = new HttpClient();
    CommunnicationThread s = new CommunnicationThread(postMethod, client);
    s.setDaemon(true);
    s.start();
    while (s.isAlive()) {
      if (monitor.isCanceled()) {
        s.interrupt();
        return new ByteArrayInputStream(new byte[0]);
      }
      try {
        s.join(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    if (s.ex != null) {
      throw s.ex;
    }
    int sc = postMethod.getStatusCode();
    if (sc == 404) {
      throw new IOException(
          "Data Store viewer is not deployed to the target server, please deploy it and try again");
    }
    if (sc != 200) {
      throw new IOException("Internal error: Incorrect Server Response ("
          + sc + ")");
    }
    return postMethod.getResponseBodyAsStream();
  }

  protected String getUrl() {
    String connectionString = null;
    new Check() {

      protected void internalRun(IJavaProject project) {

      }

    }.doCheck(project);
    if (debug) {
      int port = DebugServerLaunchManager.getPort(project);
      if (port == -1) {
        CheckLaunchJob checkLaunchJob = new CheckLaunchJob(
            "Checking Launch", project, true);
        // try {
        checkLaunchJob.schedule();
        // int a = 0;
        long l1 = System.currentTimeMillis();
        long l2 = System.currentTimeMillis();
        while (checkLaunchJob.getResult() == null && (l2 - l1) <= 30000) {

          Thread.yield();
          Display current = Display.getCurrent();
          if (current != null) {
            current.readAndDispatch();
          }
          l2 = System.currentTimeMillis();
          // a++;
        }
        // } catch (InterruptedException e) {

        // }
        port = DebugServerLaunchManager.getPort(project);
        if (port == -1) {
          return null;
        }
      }
      connectionString = "http://localhost:" + port + "/";
    } else {
      String appId = GaeBridge.getAppId(project.getProject());
      String version = GaeBridge.getVersion(project.getProject());
      if (appId == null || version == null) {
        throw new RuntimeException();
      }
      connectionString = "http://" + version + ".latest." + appId
          + ".appspot.com/";
    }
    return connectionString + "appwrench/baseviewer";
  }

  public void delete(Object[] object, OperationCallback callback) {
    Request r = new Request();
    for (Object o : object) {
      r.addPart(new Request.RemoveRequestPart(o, namespace));
    }
    try {
      communicate(r, null, new NullProgressMonitor());
      callback.passed(null);
    } catch (IOException e) {
      callback.failed(e);
    }
  }

  public Query getDefaultQuery() {
    return new Query(new Filter[0], new Sort("", false), 1000, 0);
  }

  Query lastQuery;

  protected Field[] fields;
  private Field[] chFields;

  public Field[] getChFields() {
    return chFields;
  }

  public Field[] getpFields() {
    return pFields;
  }

  private Field[] pFields;

  private String status;

  private IStatusCallback cb;

  protected int limit = -1;

  protected Job currentJob;

  public int getLimit() {
    return limit;
  }

  public void setLimit(int limit) {
    this.limit = limit;
  }

  protected void setStatus(String status) {
    if (cb != null) {
      this.status = status;
      cb.statusChanged(status);
    }
  }

  LinkedHashMap<String, Field> fieldsMap = new LinkedHashMap<String, Field>();

  protected ArrayList<Entity> objects = new ArrayList<Entity>();

  public synchronized Entity[] query(final Query query, String kind,
      IProgressMonitor monitor) throws Exception {

    lastQuery = query;
    objects.clear();

    completed = false;
    Request r = new Request();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    r.addPart(new Request.ViewRequestPart(kind, query,
        limit != -1 ? limit + 1 : -1, namespace));

    final ArrayList<Entity> results = new ArrayList<Entity>();
    objects.clear();
    Callback cb = new Callback() {

      public boolean objectFetched(Object object) {
        results.add((Entity) object);
        return true;
      }
    };
    communicate(r, cb, monitor);
    return results.toArray(new Entity[results.size()]);
  }

  public synchronized Entity[] query(final Query query, Callback c,
      IProgressMonitor monitor) throws Exception {

    lastQuery = query;
    objects.clear();

    completed = false;
    Request r = new Request();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    r.addPart(new Request.ViewRequestPart(kind, query,
        limit != -1 ? limit + 1 : -1, namespace));

    final ArrayList<Entity> results = new ArrayList<Entity>();
    objects.clear();
    communicate(r, c, monitor);
    return results.toArray(new Entity[results.size()]);
  }

  public synchronized Entity[] query(final Query query, Callback c,
      IProgressMonitor monitor, boolean forStoring) throws Exception {

    lastQuery = query;
    objects.clear();

    completed = false;
    Request r = new Request();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    r.addPart(new Request.ViewRequestPart(kind, query,
        limit != -1 ? limit + 1 : -1, forStoring, namespace));

    final ArrayList<Entity> results = new ArrayList<Entity>();
    objects.clear();
    communicate(r, c, monitor);
    return results.toArray(new Entity[results.size()]);
  }

  public synchronized Entity[] query(final Query query,
      IProgressMonitor monitor) throws Exception {

    lastQuery = query;
    objects.clear();

    completed = false;
    Request r = new Request();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    r.addPart(new Request.ViewRequestPart(kind, query,
        limit != -1 ? limit + 1 : -1, namespace));

    final ArrayList<Entity> results = new ArrayList<Entity>();
    objects.clear();
    Callback cb = new Callback() {

      public boolean objectFetched(Object object) {
        if (object instanceof Entity) {
          results.add((Entity) object);
        }
        return true;
      }
    };
    communicate(r, cb, monitor);
    return results.toArray(new Entity[results.size()]);
  }

  public synchronized void query(final Query query,
      final IDataCallback callback) {
    updateFilters(query);
    lastQuery = query;
    objects.clear();
    String url = getUrl();
    if (url == null) {
      return;
    }
    String string = "Querying data: " + kind + " (" + url + ")";
    if (currentJob != null && currentJob.getState() != Job.NONE) {
      currentJob.cancel();
      try {
        currentJob.join();
      } catch (InterruptedException e) {

      }
    }
    currentJob = new QueryJob(string, callback, query);
    currentJob.schedule();
  }

  public Field[] determineFields(List<?> results, Map<String, Field> fields) {
    if (results.isEmpty()) {
      if (this.fields == null) {
        this.fields = new Field[] {};
      }

      // return this.fields;

      Collection<String> ks = persistentFields.keySet();
      appendNeededFields(fields, new ArrayList<String>());
      appendEmbeddedFields(fields, ks);

      Field[] array = fields.values().toArray(new Field[fields.size()]);
      Arrays.sort(array);
      BaseDataFacade.this.fields = array;
      return array;

    }

    ArrayList<String> usedNames = new ArrayList();

    GAEField gaeField = new GAEField(Entity.KEY_RESERVED_PROPERTY, true);
    gaeField.setKeyKind(kind);
    GAEField oldK = (GAEField) fields.get(Entity.KEY_RESERVED_PROPERTY);

    if (oldK != null) {
      gaeField = oldK;
    } else {
      fields.put(gaeField.name, gaeField);
    }

    usedNames.add(Entity.KEY_RESERVED_PROPERTY);

    for (Object o : new ArrayList<Object>(results)) {
      com.google.appengine.api.datastore.Entity r = (Entity) o;
      Map<String, Object> properties = r.getProperties();
      // Key
      Key kv = r.getKey();
      updateValues(Entity.KEY_RESERVED_PROPERTY, kv);

      for (Entry<String, Object> m : properties.entrySet()) {
        String key = m.getKey();
        if (key.equals(ONPOSITIVE_MAGIC_SHORTENED_PROPERTIES)) {
          continue;
        }
        GAEField f = new GAEField(m.getKey(), true);
        GAEField field = (GAEField) fields.get(f.name);
        if (field != null) {
          f = field;
        } else {
          fields.put(f.name, f);
        }

        usedNames.add(f.name);
        Object value = m.getValue();

        updateValues(key, value);
        if (value != null) {
          Class<? extends Object> class1 = value.getClass();
          if (value instanceof Collection<?>) {
            f.multiplicity = true;
            Collection<?> cm = (Collection<?>) value;
            if (!cm.isEmpty()) {
              Object obj = cm.iterator().next();
              if (obj != null) {
                Class<?> t = obj.getClass();
                f.setType(t);
              }
              if (obj instanceof Key) {
                Key c = (Key) obj;
                f.setKeyKind(c.getKind());
              }
            }
          } else {
            f.setType(class1);
          }
        }
        if (value instanceof Key) {
          Key c = (Key) value;
          f.setKeyKind(c.getKind());
        }
      }
    }
    appendNeededFields(fields, usedNames);
    appendEmbeddedFields(fields, usedNames);

    Field[] array = fields.values().toArray(new Field[fields.size()]);
    Arrays.sort(array);
    BaseDataFacade.this.fields = array;
    return array;
  }

  private void appendNeededFields(Map<String, Field> fields,
      Collection<String> ks) {
    for (String us : persistentFields.keySet()) {
      if (ks.contains(us)) {
        Field f = fields.get(us);
        Class type = null;
        if (persistentFields.containsKey(us)) {
          type = persistentFields.get(us);
        }
        if (f.getType() == null) {
          f.setType(type);
          if (Collection.class.isAssignableFrom(type)) {
            ((GAEField) f).multiplicity = true;
            f.setType(null);
          }
        }
        continue;
      }
      GAEField f = new GAEField(us, true);
      // f.setKeyKind(kind);
      Class type = null;
      if (persistentFields.containsKey(us)) {
        type = persistentFields.get(us);
      }

      updateValues(us, null);
      f.setType(type);
      if (Collection.class.isAssignableFrom(type)) {
        f.multiplicity = true;
        f.setType(null);
      }

      fields.put(f.name, f);
    }
  }

  private void appendEmbeddedFields(Map<String, Field> fields,
      Collection<String> determined) {
    for (String us : embeddedFields.keySet()) {
      FieldInfo fi = embeddedFields.get(us);
      Class type = null;
      if (fi.getFieldType() != null) {
        type = fi.getFieldType();
      }
      if (determined.contains(us)) {
        Field f = fields.get(us);
        if (f.getType() == null) {
          f.setType(type);
        }
        continue;
      }
      GAEField f = new GAEField(us, true);
      // f.setKeyKind(kind);

      f.setType(type);
      updateValues(us, null);

      fields.put(f.name, f);
    }

  }

  protected void updateValues(String key, Object value) {
    if (value instanceof Collection<?>) {
      for (Object o : (Collection<?>) value) {
        updateValues(key, o);
      }
    }
    if (value instanceof Comparable<?>) {
      HashSet<Object> val = values.get(key);
      if (val == null) {
        val = new HashSet<Object>();
        values.put(key, val);
      }
      val.add(value);

    }
  }

  public void store(Object object, OperationCallback callback) {
    Request r = new Request();
    r.addPart(new Request.UpdateRequestPart(object, namespace));
    try {
      communicate(r, null, new NullProgressMonitor());
      callback.passed(object);

    } catch (IOException e) {
      callback.failed(e);
    }
  }

  public String getKind() {
    return kind;
  }

  public void refresh() {
    Query currentQuery = getCurrentQuery();
    ApiProxy.setEnvironmentForCurrentThread(new FakeEnvironment(getAppId()));
    updateFilters(currentQuery);
    if (refreshCallback != null) {
      query(currentQuery, refreshCallback);
    }
  }

  protected void updateFilters(Query currentQuery) {
    ArrayList<Filter> filters = new ArrayList<Filter>();
    if (fields != null) {
      l2: for (final Field f : fields) {
        GAEField c = (GAEField) f;
        String cText = c.cText == null ? "" : c.cText.trim();
        int operator = 0;
        if (cText.startsWith(">=")) {
          operator = Filter.GREATER_OR_EQUAL;
          cText = cText.substring(2);
        }
        if (cText.startsWith("<=")) {
          operator = Filter.LESS_OR_EQUAL;
          cText = cText.substring(2);
        }
        if (cText.startsWith("<") && !cText.startsWith("<null>")) {
          operator = Filter.LESS;
          cText = cText.substring(1);
        }
        if (cText.startsWith(">")) {
          operator = Filter.GREATER;
          cText = cText.substring(1);
        }
        if (cText.startsWith("=")) {
          operator = Filter.EQUAL;
          cText = cText.substring(1);
        }
        String filtName = f.name;
        if (filtName.equals(Entity.KEY_RESERVED_PROPERTY)) {
          filtName = "ONPOSITIVE_FILTER_FOR_PRIMARY_KEY";
        }

        if (cText != null && cText.trim().equals("<null>")) {
          filters.add(new Filter(filtName, operator, null));
          continue l2;
        }
        if (cText != null && cText.trim().length() != 0) {
          HashSet<Object> hashSet = values.get(f.name);
          if (hashSet != null) {
            for (Object o : hashSet) {
              if (c.getObjectText(o).equals(cText)) {
                filters.add(new Filter(filtName, operator, o));
                continue l2;
              }
            }
          }
          if (f.getType() == String.class) {
            filters.add(new Filter(filtName, operator, cText.trim()));
          } else if (Number.class.isAssignableFrom(f.getType())) {
            if (f.getType() == Long.class) {
              try {
                filters.add(new Filter(filtName, operator, Long
                    .parseLong(cText.trim())));
              } catch (NumberFormatException e) {
                try {
                  filters.add(new Filter(filtName, operator,
                      Double.parseDouble(cText.trim())));
                } catch (NumberFormatException e1) {
                  // just ignoring such filter
                }
              }
            } else if (f.getType() == Double.class) {
              try {
                filters.add(new Filter(filtName, operator,
                    Double.parseDouble(cText.trim())));
              } catch (NumberFormatException e) {
                // just ignoring such filter
              }
            }
          } else if (f.getType() == Key.class) {
            try {
              Key parseKey = new KeyParser().parseKey(cText
                  .trim());
              filters.add(new Filter(filtName, operator, parseKey));
            } catch (Exception e) {
              String s = cText.trim();

              if (c.name.equals(Entity.KEY_RESERVED_PROPERTY)) {
                String[] details = c.getKeyKindDetails();
                if (details != null && details.length != 0) {
                  String[] splitted = s.split(",");
                  for (int i = 0; i < details.length; i++) {
                    String ff = details[i];
                    String fv = "";
                    if (i < splitted.length) {
                      fv = splitted[i];
                      filters.add(new Filter(ff,
                          Filter.EQUAL, fv));
                    }

                  }
                }
              } else {
                filters.add(new Filter(filtName,
                    Filter.COMPLEX_FILTER,
                    new Request.ComplexFilter(s, c)));
              }
            }
          } else if (f.getType() == Date.class) {
            try {
              Date parse = dt.parse(cText);

              filters.add(new Filter(filtName, operator, parse));

            } catch (Exception e) {
              Display.getDefault().syncExec(new Runnable() {

                public void run() {
                  MessageDialog.openError(Display
                      .getCurrent().getActiveShell(),
                      "Error",
                      "Unable to parse filter for "
                          + f.name);

                }
              });
              e.printStackTrace();
            }

          }
        }
      }
    }
    currentQuery.filters = filters.toArray(new Filter[filters.size()]);
  }

  public Query getCurrentQuery() {
    return lastQuery == null ? getDefaultQuery() : lastQuery;
  }

  public Field[] getFields() {
    return fields;
  }

  public void refresh(Object object) {
    if (singleCall != null) {
      singleCall.refresh(object);
    }
  }

  String appId = null;

  public String getAppId() {
    if (appId != null) {
      return appId;
    }
    String appId2 = GaeBridge.getAppId(project.getProject());
    appId = appId2;
    return appId2;
  }

  public String getStatus() {
    return status;
  }

  public void setStatusCallback(IStatusCallback iStatusCallback) {
    this.cb = iStatusCallback;
  }

  public Entity queryFull(Entity e) throws IOException {
    Request r = new Request();
    r.addPart(new Request.GetFullRequestPart(e, namespace));
    Object[] communicate = communicate(r, null, new NullProgressMonitor());
    Object object = communicate[0];
    if (object instanceof Entity) {
      return (Entity) object;
    }
    throw new IOException(object.toString());

  }

  public IRealm<?> getRealm(Field f) {
    HashSet<Object> elements = values.get(f.name);
    if (elements != null) {
      return new Realm(elements);
    }
    return null;
  }

  public boolean isCompleted() {
    return completed;
  }

  public Object[] getCurrentElements() {
    return objects.toArray();
  }

  public IJavaProject getProject() {
    return project;
  }

  public boolean isDebug() {
    return debug;
  }

  public Field[] determineFields(List<Entity> asList) {
    return determineFields(asList, new LinkedHashMap<String, Field>());
  }

  public GAEField createField(String value, Class<?> value2,
      Boolean boolean1, String keyKind) {
    GAEField gaeField = new GAEField(value, false);
    gaeField.multiplicity = boolean1;
    gaeField.setType(value2);
    gaeField.keyKind = keyKind;
    Field[] newFields = new Field[fields.length + 1];
    System.arraycopy(fields, 0, newFields, 0, fields.length);
    newFields[fields.length] = gaeField;
    fields = newFields;
    return gaeField;
  }

  public void store(Object[] objects, OperationCallback callback) {
    Request r = new Request();
    for (Object object : objects) {
      r.addPart(new Request.UpdateRequestPart(object, namespace));
    }
    try {
      communicate(r, null, new NullProgressMonitor());
      callback.passed(objects);
    } catch (IOException e) {
      callback.failed(e);
    }
  }

  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }

  private long getJustReaded() {
    return bytesReaded;
  }

  public void updateChildren(Object obj) {
    Entity e = (Entity) obj;
    for (Iterator<String> i = kindsOfChildren.keySet().iterator(); i
        .hasNext();) {
      String var = i.next();
      String kind = kindsOfChildren.get(var);
      FindChildrenJob fchj = new FindChildrenJob("Updating children");
      fchj.setSystem(false);
      fchj.setData(new Entity[] { e });
      fchj.setKind(kind);
      fchj.schedule();

    }
  }

  public void updateParent(Object obj) {
    Entity e = (Entity) obj;
    FindParentsJob fpj = new FindParentsJob("updating parent");
    fpj.setData(new Entity[] { e });
    fpj.setSystem(true);
    fpj.schedule();
  }

  public void updateFields() {
    if (refreshCallback != null) {
      refreshCallback.fieldsFetched(fields);
    }
  }

  private class CheckStatusJob extends Job {

    private static final String STAT_KIND = "status_entity";
    private static final String STAT_ID = "job_id";
    private static final String STAT_COUNT = "count";
    private static final String STAT_TOTAL = "total";
    private static final String STAT_FINISHED = "finished";
    public static final String STAT_COUNTED = "counted";

    private long countt = 0;

    private int beginIndex = 0;
    private String id;
    private String field;
    private OperationCallback cb;
    private BaseDataFacade f;
    private String name;

    public CheckStatusJob(String name, String id, String field,
        BaseDataFacade f, OperationCallback cb) {
      super(name);
      this.name = name;
      this.id = id;
      this.field = field;
      this.cb = cb;
      this.f = f;
    }

    protected IStatus run(IProgressMonitor monitor) {
      Request r = new Request();
      Entity status = null;
      int count = 0;
      boolean finished = false;
      boolean counted = false;
      boolean first = true;
      long doneTMP = 0;
      int delta = 0;
      monitor.beginTask("Calculate entities...", 100);
      monitor.worked(1);
      do {
        try {
          Thread.sleep(2000);
          status = checkDone();
          if (status == null) {
            break;
          } else {
            finished = (Boolean) status.getProperty(STAT_FINISHED);
            long total = (Long) status.getProperty(STAT_TOTAL);
            long done = (Long) status.getProperty(STAT_COUNT);
            counted = (Boolean) status.getProperty(STAT_COUNTED);
            if (done < 0 && counted) {
              done = 0;
              countt++;
            } else {
              countt = 0;
            }
            if (counted) {
              if (first) {
                if (total < 0) {
                  total = 1;
                }
                monitor.beginTask(name, (int) total);
                first = false;
              }
              delta = (int) (((done - doneTMP)));
              doneTMP = done;
            }
            if (delta != 0) {
              monitor.worked(delta);
            }
          }
        } catch (IOException e) {
          e.printStackTrace();
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      } while (!finished && countt < 100);

      if (field != null && field.length() != 0) {
        fieldsMap.remove(field);
      }
      refresh();
      return Status.OK_STATUS;
    }

    private Entity checkDone() throws IOException {
      int res = 0;

      Request r = new Request();
      r.addPart(new Request.CheckStatusRequestPart(f.namespace, f.kind,
          id));

      Object[] o = f.communicate(r, null, new NullProgressMonitor());
      if (o == null || o.length != 1) {
        String status = o == null ? "null" : o.length + "";
        cb.failed(new Exception("Internal Error: Incorect Results ("
            + status + ")"));
        return null;
      }
      Entity e = (Entity) o[0];
      return e;
    }
  }

  public void removeAll(OperationCallback callback) {
    Request r = new Request();

    try {
      r.addPart(new Request.RemoveAllRequestPart(namespace, kind));

      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);

      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Removing entities in progress..", id, "", copy,
            callback);
        job.schedule();

        callback.passed(null);
      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public void renameProperty(String oldProp, String newProp,
      OperationCallback callback) {
    Request r = new Request();

    try {
      r.addPart(new Request.RenamePropertyRequestPart(namespace, kind,
          oldProp, newProp));

      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);
      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Renaming of property in progress..", id, oldProp,
            copy, callback);
        job.schedule();

      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public void removeProperty(String prop, OperationCallback callback) {
    Request r = new Request();

    try {
      r.addPart(new Request.RemovePropertyRequestPart(namespace, kind,
          prop));

      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);

      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Removing of property in progress..", id, prop, copy,
            callback);
        job.schedule();

      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public void duplicateEntity(final Entity ent, final int count,
      final OperationCallback callback) {

    Request r = new Request();

    try {
      if (NameSpaceFunctionality.isSupported()) {
        String old = NameSpaceFunctionality.getNamespace();
        NameSpaceFunctionality.setNameSpace(namespace);
        String kkey = KeyFactory.keyToString(ent.getKey());
        NameSpaceFunctionality.setNameSpace(old);
        r.addPart(new Request.CopyEntityRequestPart(namespace, count,
            kkey, kind));
      } else {
        String kkey = KeyFactory.keyToString(ent.getKey());
        r.addPart(new Request.CopyEntityRequestPart(namespace, count,
            kkey, kind));
      }
      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);

      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Copying entities in progress", id, "", copy, callback);
        job.schedule();

        callback.passed(null);
      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public Field getField(String name) {
    for (Field f : fields) {
      if (f.name.equals(name)) {
        return f;
      }
    }
    return null;
  }

  private ArrayList<IChangeNamespaceListener> namespaceListeners;

  public void addChangeNamespaceListener(IChangeNamespaceListener listener) {
    if (namespaceListeners == null) {
      namespaceListeners = new ArrayList<IChangeNamespaceListener>();
    }
    namespaceListeners.add(listener);
  }

  public void removeChangeNamespaceListener(IChangeNamespaceListener listener) {
    if (namespaceListeners != null) {
      namespaceListeners.remove(listener);
    }
  }

  public void handleChangingNamespace() {
    for (IChangeNamespaceListener l : namespaceListeners) {
      l.handleChanging(getNamespace());
    }
  }

  public void changeIndexation(String property, boolean makeUnindexed,
      OperationCallback callback) {
    Request r = new Request();

    try {
      r.addPart(new Request.ChandgeIndexationRequestPart(namespace, kind,
          property, makeUnindexed));

      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);

      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Change of indexation for property in progress..", id,
            property, copy, callback);
        job.schedule();

      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }

  public void setPropertyValue(String property, Entity value,
      boolean byDefault, OperationCallback callback) {
    Request r = new Request();

    try {
      r.addPart(new Request.SetPropertyValueRequestPart(namespace,
          property, value, byDefault));

      BaseDataFacade copy = new BaseDataFacade(kind, project, pm,
          isDebug());
      copy.setNamespace(namespace);

      try {
        Object[] res = communicate(r, null, new NullProgressMonitor());
        String id = null;
        if (res.length == 1) {
          id = (String) res[0];
        }

        CheckStatusJob job = new CheckStatusJob(
            "Inserting value for property...", id, property, copy,
            callback);
        job.schedule();

      } catch (IOException e) {
        callback.failed(e);
      }
    } catch (SecurityException e1) {
      callback.failed(e1);
    }
  }
}
TOP

Related Classes of com.onpositive.gae.baseviewer.BaseDataFacade$Callback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.
pt','//www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-20639858-1', 'auto'); ga('send', 'pageview');