Android Open Source - DKO Soft Join






From Project

Back to project page DKO.

License

The source code is released under:

GNU Lesser General Public License

If you think the Android project DKO listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package org.kered.dko;
//from www .j a  v  a  2s. c  o  m
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;

import javax.sql.DataSource;

import org.kered.dko.Constants.DB_TYPE;
import org.kered.dko.Constants.DIRECTION;
import org.kered.dko.Constants.JOIN_TYPE;
import org.kered.dko.Field.FK;

class SoftJoin<T extends Table> extends AbstractQuery<T> {

  private static final Logger log = Logger
      .getLogger("org.kered.dko.SoftJoin");

  private Query<? extends Table> q1;
  private Query<? extends Table> q2;
  private Condition condition;
  private final JOIN_TYPE joinType;
  //private Class<? extends J> type;
  private long limit = -1;

  private transient List<Field<?>> selectFields;



  public SoftJoin(final JOIN_TYPE joinType,
      final Class<? extends Table> type,
      final Class<? extends Table> t1, final Class<? extends Table> t2,
      final Condition on) {
    super(type);
    this.joinType = joinType;
    q1 = QueryFactory.IT.getQuery(t1);
    q2 = QueryFactory.IT.getQuery(t2);
    if (on!=null) joinAwareWhere(on);
  }

  public SoftJoin(final SoftJoin<T> q) {
    super(q.ofType);
    joinType = q.joinType;
    q1 = q.q1;
    q2 = q.q2;
    condition = q.condition;
    limit = q.limit;
  }

  public SoftJoin(final JOIN_TYPE joinType, final Class<? extends Table> type, final Query<? extends Table> q, final Class<? extends Table> t, final Condition on) {
    super(type);
    this.joinType = joinType;
    q1 = q;
    q2 = QueryFactory.IT.getQuery(t);
    if (on!=null) joinAwareWhere(on);
  }

  @Override
  public Query<T> where(final Condition... conditions) {
    final SoftJoin<T> q = new SoftJoin<T>(this);
    q.joinAwareWhere(conditions);
    return q;
  }

  private void joinAwareWhere(final Condition... conditions) {
    for (final Condition condition : conditions) {
      if (SoftJoinUtil.conditionIsAllReferencingQuery(condition, q1)) {
        q1 = q1.where(condition);
      } else if (SoftJoinUtil.conditionIsAllReferencingQuery(condition, q2)) {
        q2 = q2.where(condition);
      } else {
        if (this.condition==null) this.condition = condition;
        else this.condition = this.condition.and(condition);
      }
    }
  }

  @Override
  public Query<T> limit(final long n) {
    final SoftJoin<T> q = new SoftJoin<T>(this);
    q.limit = n;
    return q;
  }

  @Override
  public Query<T> distinct() {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> max() {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> min() {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> with(final FK... fields) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> deferFields(final Field<?>... fields) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> deferFields(final Collection<Field<?>> fields) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> onlyFields(final Collection<Field<?>> fields) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> onlyFields(final Field<?>... fields) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public Query<T> set(final Field<?> key, final Object value) {
    throw new UnsupportedOperationException(
        "Write operations are not supported in software joins.");
  }

  @Override
  public Query<T> set(final Map<Field<?>, Object> values) {
    throw new UnsupportedOperationException(
        "Write operations are not supported in software joins.");
  }

  @Override
  public Query<T> use(final DataSource ds) {
    log.warning("Setting a data source doesn't make sense in a software join.  You probably want to set it on one of the consituant queries.");
    return this;
  }

  @Override
  public Query<T> use(final Connection conn) {
    log.warning("Setting a connection doesn't make sense in a software join.  You probably want to set it on one of the consituant queries.");
    return this;
  }

  @Override
  public Query<T> use(final DB_TYPE type) {
    log.warning("Setting a database type doesn't make sense in a software join.  You probably want to set it on one of the consituant queries.");
    return this;
  }

  @Override
  public Query<T> in(final Collection<T> set) {
    throw new RuntimeException("not implemented yet"); // TODO
  }

  @Override
  public DataSource getDataSource() {
    return q1.getDataSource();
  }

  @Override
  public List<Field<?>> getSelectFields() {
    if (selectFields == null) {
      selectFields = new ArrayList<Field<?>>();
      selectFields.addAll(q1.getSelectFields());
      selectFields.addAll(q2.getSelectFields());
      selectFields = Collections.unmodifiableList(selectFields);
    }
    return selectFields;
  }

  @Override
  public Iterator<T> iterator() {

      final long q1Rows = UsageStats.estimateRowCount(q1);
      final long q2Rows = UsageStats.estimateRowCount(q2);
    System.err.println("q1Rows "+ q1.getType().getName() +" "+ q1.hashCode() +" "+ q1Rows);
    System.err.println("q2Rows "+ q2.getType().getName() +" "+ q2.hashCode() +" "+ q2Rows);
      final Iterable<? extends Table> qXa;
      final Iterable<? extends Table> qYa;
      final Iterable<? extends Table> q1nulled = (this.joinType==Constants.JOIN_TYPE.RIGHT || this.joinType==Constants.JOIN_TYPE.OUTER) ? new SoftJoinUtil.AddNullAtEnd(q1) : q1;
      final Iterable<? extends Table> q2nulled = (this.joinType==Constants.JOIN_TYPE.LEFT || this.joinType==Constants.JOIN_TYPE.OUTER) ? new SoftJoinUtil.AddNullAtEnd(q2) : q2;
      final boolean swapped;
      final boolean q1pk, q2pk;
      final boolean qXpk, qYpk;
      final Map<Field<?>, Field<?>> fieldOpposingPK;
    q1pk = SoftJoinUtil.doesConditionCoverPK(q1.getType(), condition);
    q2pk = SoftJoinUtil.doesConditionCoverPK(q2.getType(), condition);
    if (q1Rows > q2Rows) { // && !(q2pk && !q1pk)
        qXa = q1nulled;
        qYa = new LazyCacheIterable(q2nulled, (int) (q2Rows*1.1));
        swapped = false;
      qXpk = q1pk;
      if (qXpk) fieldOpposingPK = SoftJoinUtil.getFieldsOpposingPK(q1.getType(), condition);
      else fieldOpposingPK = null;
      qYpk = q2pk;
      } else {
        qXa = q2nulled;
        qYa = new LazyCacheIterable(q1nulled, (int) (q1Rows*1.1));
        swapped = true;
      qXpk = q2pk;
      if (qXpk) fieldOpposingPK = SoftJoinUtil.getFieldsOpposingPK(q2.getType(), condition);
      else fieldOpposingPK = null;
      qYpk = q1pk;
      }
    
    System.err.println("swapped: "+ swapped);
    System.err.println("q1.getType(): "+ q1.getType());
    System.err.println("q2.getType(): "+ q2.getType());
    Constructor c = null;
    try {
      c = getType().getDeclaredConstructor(Table.class, Table.class);
      if (!c.isAccessible()) c.setAccessible(true);
    } catch (final SecurityException e) {
      e.printStackTrace();
    } catch (final NoSuchMethodException e) {
      e.printStackTrace();
    }
    final Set<Field<?>> fields = Collections.unmodifiableSet(new HashSet<Field<?>>(getSelectFields()));
    final Constructor jc = c;
    final int st1 = SoftJoinUtil.getObjectSizeOfQuery(q1);
    final int st2 = SoftJoinUtil.getObjectSizeOfQuery(q2);

    return new ClosableIterator<T>() {

      Iterator<? extends Table> qXi = qXa.iterator();
      Iterator<? extends Table> qYi = qYa.iterator();
      boolean matchedqX = false;
      boolean matchedqY = false;
      long count = 0;
      Table tX = null;
      private T next;
      boolean first = true;
      boolean firstPassQY = true;

      @Override
      public boolean hasNext() {
        if (next!=null) return true;
        if ((limit>=0 && count>=limit)) {
          close();
          return false;
        }
        while (qXi.hasNext() || (qYi!=null && qYi.hasNext())) {
          final T t = peekNext();
          if (t==null) continue;
          if (tX==null && qXi.hasNext()) tX = qXi.next();
          boolean matches = true;
          if (condition!=null) {
            Object qXo = swapped ? ((Join)t).r : ((Join)t).l;
            Object qYo = swapped ? ((Join)t).l : ((Join)t).r;
            if (!matchedqX && qXo==null) {
              matchedqX = true;
            } else if (!matchedqY && qYo==null) {
              matchedqY = true;
            } else {
              matches &= condition.matches(t);
              if (matches) {
                matchedqX = true;
                matchedqY = true;
              }
            }
          }
          if (matches) {
            next = t;
            if (qYpk) {
              if (qXi.hasNext()) {
                qYi = qYa.iterator();
                firstPassQY = false;
                tX = qXi.next();
              } else {
                qYi = null;
              }
            }
            return true;
          }
        }
        close();
        return false;
      }

      @Override
      public T next() {
        ++count;
        final T ret = next;
        next = null;
        return ret;
      }
      
      Set<List> seenTYKeys = new HashSet<List>();
      private List lastTXPKValue = null;

      public T peekNext() {
        if (first) {
          first = false;
          if (qXi.hasNext()) {
            tX = qXi.next();
            if (qXpk) registerTX();
          }
          else return null;
        }
        final Table tY;
        if (!qYi.hasNext() && qXi.hasNext()) {
          tX = qXi.next();
          if (qXpk) {
            List values = registerTX();
            while (!isT1inT2(values)) {
              if (qXi.hasNext()) {
                tX = qXi.next();
                values = registerTX();
              } else {
                return null;
              }
            }
          }
          if (qYi instanceof ClosableIterator) ((ClosableIterator)qYi).close();
          if (qXpk && weHitAll()) return null;
          qYi = qYa.iterator();
          firstPassQY = false;
          matchedqY = false;
          if (!qYi.hasNext()) return null;
          tY = qYi.next();
        } else {
          tY = qYi.next();
        }
        if (firstPassQY && qXpk) registerTY(tY);
        try {
          if (swapped) {
            return (T) jc.newInstance(tY, tX);
          } else {
            return (T) jc.newInstance(tX, tY);
          }
        } catch (final IllegalArgumentException e) {
          e.printStackTrace();
        } catch (final InstantiationException e) {
          e.printStackTrace();
        } catch (final IllegalAccessException e) {
          e.printStackTrace();
        } catch (final InvocationTargetException e) {
          e.printStackTrace();
        }
        return null;
      }

      private boolean isT1inT2(List values) {
        return seenTYKeys.contains(values);
      }

      private List registerTX() {
        if (tX==null) return Collections.emptyList();
        List values = new ArrayList();
        for (Field<?> f : fieldOpposingPK.keySet()) {
          values.add(tX.get(f));
        }
        this.lastTXPKValue = values;
        return values;
      }

      private void registerTY(Table t2) {
        List values = new ArrayList();
        for (Field<?> f : fieldOpposingPK.values()) {
          values.add(t2.get(f));
        }
        seenTYKeys.add(values);
      }

      private boolean weHitAll() {
        Set<List> keysLeft = seenTYKeys; //new HashSet<List>(seenTYKeys);
        keysLeft.remove(lastTXPKValue);
        boolean weHitAll = keysLeft.isEmpty();
        if (!weHitAll) {
          int size = keysLeft.size();
          if (size%10==0 || size<10) System.err.println("weHitAll? "+ weHitAll +" "+ size);
        }
        return weHitAll;
      }

//      private Table addNullForSomeJoins(final Iterator<? extends Table> i) {
//        return joinType==JOIN_TYPE.LEFT || joinType==JOIN_TYPE.OUTER ? null : (i.hasNext() ? i.next() : null);
//      }
//
//      private Table addNullForOtherJoins(final Iterator<? extends Table> i) {
//        return joinType==JOIN_TYPE.RIGHT || joinType==JOIN_TYPE.OUTER ? null : (i.hasNext() ? i.next() : null);
//      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }

      @Override
      public void close() {
        if (qXi instanceof ClosableIterator) ((ClosableIterator)qXi).close();
        if (qYi instanceof ClosableIterator) ((ClosableIterator)qYi).close();
      }
    };
  }

  @Override
  public Query<T> avg() {
    // TODO Auto-generated method stub
    return null;
  }

  @Override
  public Query<T> orderBy(Expression.OrderBy<?>... obes) {
    throw new RuntimeException("not implemented yet"); // TODO
  }


}




Java Source Code List

.HelloWorld.java
org.kered.contactlensfinder.DB.java
org.kered.contactlensfinder.MainActivity.java
org.kered.contactlensfinder.ViewManufacturersActivity.java
org.kered.contactlensfinder.ViewProductsActivity.java
org.kered.contactlensfinder.ViewPropertiesActivity.java
org.kered.dko.AbstractQuery.java
org.kered.dko.Bulk.java
org.kered.dko.CSV.java
org.kered.dko.ClosableIterator.java
org.kered.dko.Condition.java
org.kered.dko.Constants.java
org.kered.dko.Context.java
org.kered.dko.DBQuery.java
org.kered.dko.DBRowIterator.java
org.kered.dko.Diff.java
org.kered.dko.DualIterator.java
org.kered.dko.Expression.java
org.kered.dko.Field.java
org.kered.dko.FilteringQuery.java
org.kered.dko.Function.java
org.kered.dko.InMemoryQuery.java
org.kered.dko.Join.java
org.kered.dko.LazyCacheIterable.java
org.kered.dko.LocalJoin.java
org.kered.dko.M.java
org.kered.dko.Main.java
org.kered.dko.MatryoshkaQuery.java
org.kered.dko.PeekableClosableIterator.java
org.kered.dko.PeekableIterator.java
org.kered.dko.QueryAddField.java
org.kered.dko.QueryFactory.java
org.kered.dko.QuerySnapshot.java
org.kered.dko.Query.java
org.kered.dko.SQLFunction.java
org.kered.dko.SelectAsMapIterable.java
org.kered.dko.SelectFromOAI.java
org.kered.dko.SelectSingleColumn.java
org.kered.dko.SoftJoinUtil.java
org.kered.dko.SoftJoin.java
org.kered.dko.SqlContext.java
org.kered.dko.Statistics.java
org.kered.dko.SubQueryField.java
org.kered.dko.TableInfo.java
org.kered.dko.TableWrapper.java
org.kered.dko.Table.java
org.kered.dko.TemporaryTableFactory.java
org.kered.dko.TmpTableBuilder.java
org.kered.dko.Tuple.java
org.kered.dko.UsageMonitor.java
org.kered.dko.UsageStats.java
org.kered.dko.Util.java
org.kered.dko.ant.ClassGenerator.java
org.kered.dko.ant.CodeGeneratorBase.java
org.kered.dko.ant.CodeGenerator.java
org.kered.dko.ant.DataSourceGenerator.java
org.kered.dko.ant.GsonGenerator.java
org.kered.dko.ant.JoinGenerator.java
org.kered.dko.ant.Main.java
org.kered.dko.ant.SchemaExtractorBase.java
org.kered.dko.ant.SchemaExtractor.java
org.kered.dko.ant.Util.java
org.kered.dko.datasource.CheapConnectionPoolingDataSource.java
org.kered.dko.datasource.ConnectionCountingDataSource.java
org.kered.dko.datasource.JDBCDriverDataSource.java
org.kered.dko.datasource.MatryoshkaDataSource.java
org.kered.dko.datasource.MirroredDataSource.java
org.kered.dko.datasource.ReflectedDataSource.java
org.kered.dko.datasource.SingleConnectionDataSource.java
org.kered.dko.datasource.SingleThreadedDataSource.java
org.kered.dko.datasource.UnClosableConnection.java
org.kered.dko.datasource.Util.java
org.kered.dko.json.CDL.java
org.kered.dko.json.CookieList.java
org.kered.dko.json.Cookie.java
org.kered.dko.json.HTTPTokener.java
org.kered.dko.json.HTTP.java
org.kered.dko.json.JSONArray.java
org.kered.dko.json.JSONException.java
org.kered.dko.json.JSONML.java
org.kered.dko.json.JSONObject.java
org.kered.dko.json.JSONString.java
org.kered.dko.json.JSONStringer.java
org.kered.dko.json.JSONTokener.java
org.kered.dko.json.JSONWriter.java
org.kered.dko.json.Pickle.java
org.kered.dko.json.XMLTokener.java
org.kered.dko.json.XML.java
org.kered.dko.junk.DerbyLoadTestSchema.java
org.kered.dko.junk.OracleCreateTestUser.java
org.kered.dko.junk.OracleLoadTestSchema.java
org.kered.dko.persistence.Util.java
org.kered.dko.util.DumpDatabase.java
sakila.Example0.java
sakila.Example1.java
sakila.Example2.java
sakila.Util.java